#include "header.h"
void api_cb_ns_rpc_api_response(NS_RPC_RESPONSE *r){
jrnl_free_request(r->request);
}
USER *api_user(NS_RPC_REQUEST *r){
USER *u=user_of_connection(r->c);
if(u){
user_init_alarm_objects(u);
free(u->temp_project);
free(u->temp_groups);
u->temp_project=NULL;
u->temp_groups=NULL;
}
return u;
}
USER_SESSION *api_session_con(NS_RPC_CONNECTION *c){
if(c && c->is_incoming){
return obj_payload(c->fn_data);
}else{
return NULL;
}
}
USER_SESSION *api_session(NS_RPC_REQUEST *r){
return api_session_con(r->c);
}
bool api_is_registered_user(NS_RPC_REQUEST *r){
USER *u=api_user(r);
if(u && !u->anonymous){
return 1;
}else{
ns_rpc_response_err(r,SERVER_ERROR_ACCESS_DENIED);
return 0;
}
}
USER *api_user_con(NS_RPC_CONNECTION *c){
USER *u=user_of_session(c->fn_data);
if(u && !u->blocked){
user_init_alarm_objects(u);
return u;
}else{
return NULL;
}
}
bool api_required(NS_RPC_REQUEST *r, char *params){
char *p;
if(strcmp(params,"params")==0){
if(!r->params){
ns_rpc_response_err(r,NS_RPC_ERROR_PARAMS);
return 0;
}
return 1;
}else{
str_iter_bgn(params,",",p)
if(!json_tok(r->params,p)){
ns_rpc_response_err(r,NS_RPC_ERROR_PARAMS);
return 0;
}
str_iter_end
return 1;
}
}
bool api_is_user(NS_RPC_REQUEST *r){
if(api_user(r)){
return 1;
}else{
ns_rpc_response_err(r,SERVER_ERROR_ACCESS_DENIED);
return 0;
}
}
bool api_is_admin_con(NS_RPC_CONNECTION *c){
USER *u=user_of_session(c->fn_data);
if(u) return u->admin && !u->blocked;
return 0;
}
bool api_is_user_con(NS_RPC_CONNECTION *c){
USER *u=user_of_session(c->fn_data);
if(u) return !u->blocked;
return 0;
}
bool api_is_admin(NS_RPC_REQUEST *r){
if(api_is_admin_con(r->c)){
return 1;
}else{
ns_rpc_response_err(r,SERVER_ERROR_ADMIN_ACCESS_REQUIRED);
return 0;
}
}
void api_check_apikey(NS_RPC_REQUEST *r){
if(r->params && r->params->type==JSON_TYPE_OBJECT){
char *apikey=json_str(r->params,"pult_apikey");
if(user_check_apikey(apikey)==0){
USER *u=api_user(r);
if(u && str_cmp(u->apikey,apikey)!=0){
USER_SESSION *us=api_session(r);
user_tokout(us->login,us->token);
user_unbind_session(r->c);
u=NULL;
}
if(!u){
char *ip=r->c->tcp_host;
USER_SESSION *us=user_apikey_session(apikey);
if(us){
user_tokin(us->login,us->token,ip);
user_bind_session(r->c,us);
}
}
}
}
}
bool api_is_write_access(NS_RPC_REQUEST *r){
USER *u=api_user(r);
if(u && !u->blocked && !u->readonly){
return 1;
}else{
ns_rpc_response_err(r,SERVER_ERROR_READONLY_ACCESS);
return 0;
}
}
bool api_is_editor_access(NS_RPC_REQUEST *r){
USER *u=api_user(r);
if(u && !u->blocked && u->editor_access){
return 1;
}else{
ns_rpc_response_err(r,SERVER_ERROR_ACCESS_DENIED);
return 0;
}
}
void api_cb_ns_rpc_api_request(NS_RPC_REQUEST *r){
api_check_apikey(r);
jrnl_init_request(r);
}
////////////////////////////////////////////////////////////////////////////
void api_system_delete_logs(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"service")) return;
char *service=json_str(r->params,"service");
jrnl(r,JRNL_SYSTEM_DELETE_LOGS,"object",service,NULL);
char dir[PATH_MAX];
snprintf(dir,sizeof(dir),"%s/%s/logs",path_services_dir,service);
errno=0;
file_remove_dir_content(dir);
ns_rpc_response(r,0);
}
void api_system_log_files(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_required(r,"service")) return;
char *service=json_str(r->params,"service");
char dir[PATH_MAX];
snprintf(dir,sizeof(dir),"%s/%s/logs",path_services_dir,service);
JSTR s;
jstr_init(&s,1024);
jstr_opn_arr(&s);
char *name;
char *path;
file_iter_sort_bgn(dir,FILE_TYPE_FILE,FILE_SORT_BY_NAME_ASC,name,path)
jstr_opn_obj(&s);
jstr_akey_ustr(&s,"name",0,name,0);
jstr_akey_int(&s,"size",0,file_size(path));
jstr_cls_obj(&s);
file_iter_sort_end
jstr_cls_arr(&s);
ns_rpc_response_raw_result(r,s.text,s.len);
jstr_free(&s);
}
void api_system_config_data(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_required(r,"service")) return;
char p[PATH_MAX];
char *service=json_str(r->params,"service");
sprintf(p,"%s/%s/%s",path_services_dir,service,"config.cfg");
JSTR *s=&temp_str;
jstr_reset(s);
cfg_get_config_json(p,s);
ns_rpc_response_raw_result(r,s->text,s->len);
}
void api_system_config_schema(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_required(r,"service")) return;
char p[PATH_MAX];
char *service=json_str(r->params,"service");
sprintf(p,"%s/%s/%s",path_services_dir,service,"config.shema");
JSTR *s=&temp_str;
jstr_reset(s);
cfg_get_schema_json(p,s);
ns_rpc_response_raw_result(r,s->text,s->len);
}
void api_system_services(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(srv_supervisor->connected){
ns_rpc_request_proxy(srv_supervisor->c,"list",r);
}else{
ns_rpc_response_err(r,SERVER_ERROR_SUPERVISOR_OFFLINE);
}
}
void api_system_info(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
jstr_reset(&temp_str);
jstr_opn_obj(&temp_str);
jstr_akey_int(&temp_str,"version_number",0,VERSION_NUMBER);
jstr_akey_astr(&temp_str,"version_date",0,VERSION_DATE,0);
jstr_akey_int(&temp_str,"time_startup",0,stat_time_startup);
jstr_akey_int(&temp_str,"time_stamp",0,time_ms());
jstr_akey_int(&temp_str,"time_zone",0,time_zone_offset()/60);
jstr_akey_int(&temp_str,"total_vars",0,var_count);
jstr_akey_int(&temp_str,"physical_vars",0,stat_physical_vars_cnt);
jstr_akey_int(&temp_str,"trend_vars",0,stat_trend_vars_cnt);
jstr_akey_int(&temp_str,"alarm_vars",0,stat_alarm_vars_cnt);
jstr_akey_int(&temp_str,"license_vars",0,license_vars);
jstr_akey_int(&temp_str,"signals",0,stat_core_changes);
jstr_akey_dbl(&temp_str,"signals_per_second",0,stat_signals_per_second);
jstr_akey_int(&temp_str,"gateway_count",0,stat_gateway_count);
jstr_akey_int(&temp_str,"gateway_online",0,stat_gateway_online);
jstr_akey_int(&temp_str,"gateway_incoming_traffic",0,stat_gateway_incoming_traffic);
jstr_akey_int(&temp_str,"gateway_outgoing_traffic",0,stat_gateway_outgoing_traffic);
jstr_akey_dbl(&temp_str,"gateway_incoming_traffic_per_second",0,stat_gateway_incoming_traffic_per_second);
jstr_akey_dbl(&temp_str,"gateway_outgoing_traffic_per_second",0,stat_gateway_outgoing_traffic_per_second);
jstr_akey_int(&temp_str,"service_count",0,stat_supervisor_app_count);
jstr_akey_int(&temp_str,"service_runnings",0,stat_supervisor_app_runnings);
jstr_akey_int(&temp_str,"service_errors",0,stat_supervisor_app_errors);
jstr_akey_int(&temp_str,"space_free",0,stat_supervisor_space_free);
jstr_akey_int(&temp_str,"space_total",0,stat_supervisor_space_total);
jstr_akey_int(&temp_str,"mem_usage",0,stat_supervisor_mem_usage);
jstr_akey_int(&temp_str,"mem_total",0,stat_supervisor_mem_total);
jstr_akey_dbl(&temp_str,"cpu_usage",0,stat_supervisor_cpu_usage);
jstr_akey_dbl(&temp_str,"cpu_usage_avg",0,stat_supervisor_cpu_usage_avg);
jstr_akey_int(&temp_str,"connections",0,ns_stat_active_tcp_connections);
jstr_akey_int(&temp_str,"accepts",0,ns_stat_tcp_accept_requests);
jstr_akey_int(&temp_str,"subscriptions",0,ns_rpc_stat_subscriptions_count);
jstr_cls_obj(&temp_str);
ns_rpc_response_raw_result(r,temp_str.text,temp_str.len);
}
void api_system_time(NS_RPC_REQUEST *r){
jstr_reset(&temp_str);
jstr_opn_obj(&temp_str);
jstr_akey_int(&temp_str,"time",0,time_ms());
jstr_akey_int(&temp_str,"zone",0,time_zone_offset()/60); // in minutes
jstr_akey_int(&temp_str,"os_time",0,time_ms_real());
jstr_akey_int(&temp_str,"os_zone",0,time_get_system_zone()/60); // in minutes
jstr_cls_obj(&temp_str);
ns_rpc_response_raw_result(r,temp_str.text,temp_str.len);
}
void api_system_set_time(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
uint32_t ts=json_int(r->params,"time");
int32_t tz=json_int(r->params,"zone"); // in minutes
int64_t dt=(int64_t)ts*1000UL - time_ms();
time_correct(dt);
time_set_zone(tz*60);
double dts=(double)ts;
jrnl(r,JRNL_SYSTEM_SET_TIME,"value",dts,NULL);
prj_need_refresh(1);
ns_rpc_response_true(r);
}
void api_system_reset_time(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
time_reset_correction();
jrnl(r,JRNL_SYSTEM_RESET_TIME,NULL);
ns_rpc_response_true(r);
}
void api_system_ping(NS_RPC_REQUEST *r){
ns_rpc_response_true(r);
}
void api_system_ready(NS_RPC_REQUEST *r){
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_int(s,"startup",0,stat_time_startup);
jstr_akey_int(s,"version_number",0,VERSION_NUMBER);
jstr_akey_astr(s,"version_date",0,VERSION_DATE,0);
jstr_akey_int(s,"save_counter",0,save_counter);
jstr_akey_int(s,"license_exceeded",0,stat_physical_vars_cnt > license_vars);
jstr_cls_obj(s);
ns_rpc_response_raw_result(r,s->text,s->len);
}
void api_system_get_calendar(NS_RPC_REQUEST *r){
if(!param_calendar_public_access && !api_is_user(r)) return;
char *calendar=file_read_text(param_calendar_file);
uint32_t fm=file_modified(param_calendar_file);
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_astr(s,"calendar",0,calendar,0);
jstr_akey_int(s,"edited",0,fm);
if(param_sync_calendar_enabled){
jstr_akey_int(s,"sync_last_time",0,sync_calendar_last_time);
jstr_akey_int(s,"sync_last_error",0,sync_calendar_last_error);
jstr_akey_ustr(s,"sync_url",0,param_sync_calendar_url,0);
}
jstr_cls_obj(s);
ns_rpc_response_raw_result(r,s->text,s->len);
free(calendar);
}
void api_system_set_calendar(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"calendar")) return;
int err=0;
char *calendar=json_str(r->params,"calendar");
int len=json_size(r->params,"calendar");
if(len % CALENDAR_YEAR_SIZE != 0){
err=SERVER_ERROR_INVALID_FORMAT;
goto exit;
}
int rc=file_write(param_calendar_file,calendar,-1);
if(rc<0) err=errno;
exit:
ns_rpc_response(r,err);
}
void api_user_resetpass(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"login,password")) return;
int err=0;
char *login=json_str(r->params,"login");
char *password=json_str(r->params,"password");
bool changepass=json_int(r->params,"changepass");
if(strcmp(login,"anonymous")==0) err=SERVER_ERROR_OPERATION_FAILED;
if(err) goto exit;
err=user_reset_password(login,password,changepass);
if(err) goto exit;
user_close_sessions(login,NULL);
exit:
jrnl(r,JRNL_SECURITY_RESET_PASSWORD,"object",login,"error",err,NULL);
ns_rpc_response(r,err);
}
void api_user_delete(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"login")) return;
USER *u=api_user(r);
int err=0;
char *login=json_str(r->params,"login");
if(strcmp(login,"anonymous")==0) err=SERVER_ERROR_UNABLE_DELETE_SYSTEM_USER;
if(err) goto exit;
if(strcmp(login,param_demo_login)==0) err=SERVER_ERROR_UNABLE_DELETE_SYSTEM_USER;
if(err) goto exit;
if(strcmp(login,u->login)==0) err=SERVER_ERROR_DELETE_SELF;
if(err) goto exit;
user_close_sessions(login,NULL);
err=user_delete(login);
if(err) goto exit;
exit:
jrnl(r,JRNL_SECURITY_DELETE_USER,"object",login,"error",err,NULL);
ns_rpc_response(r,err);
}
void api_user_notifications_watched(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
USER *u=api_user(r);
char *params=str_f("{\"user\":\"%s\"}",u->login);
ns_rpc_request_back(srv_db->c,"notification_watch",params,0,r);
free(params);
}
void api_user_notifications(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
USER *u=api_user(r);
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_ustr(s,"user",0,u->login,0);
if(json_exist(r->params,"watched")) jstr_akey_int(s,"watched",0,json_bool(r->params,"watched"));
if(json_exist(r->params,"from")) jstr_akey_int(s,"from",0,json_int(r->params,"from"));
jstr_cls_obj(s);
ns_rpc_request_back(srv_db->c,"notification_read",s->text,s->len,r);
}
void api_user_login(NS_RPC_REQUEST *r){
if(!api_required(r,"login")) return;
int err=0;
char token[USER_TOKEN_SIZE];
char *login=json_param_str(r->params,"login");
char *password=json_param_str(r->params,"password");
char *browser=json_param_str(r->params,"browser");
int remember=json_param_int(r->params,"remember");
if(!browser) browser="Unknown";
if(!password) password="";
char *ip=r->c->tcp_host;
err=user_login(login,password,remember,ip,browser,token);
if(err) goto exit;
exit:
jrnl(r,JRNL_SECURITY_USER_LOGIN,"executor",login,"error",err,"data",str("{\"browser\":\"%s\"}",browser),NULL);
if(err){
ns_rpc_response_err(r,err);
char *msg=langf(&lng,"ntf_error_login",ip,browser);
USER *u=user(login);
ntf_send_regular_notification(u,NTF_TYPE_ERROR,msg,NULL);
}else{
ns_rpc_response_str(r,token,0);
char *msg=langf(&lng,"ntf_success_login",ip,browser);
char *tok=user_gettok(token);
USER *u=user(login);
ntf_send_regular_notification(u,NTF_TYPE_LOGIN,msg,tok);
}
}
void api_user_tokin(NS_RPC_REQUEST *r){
if(!api_required(r,"login,token")) return;
int err=0;
char *login=json_param_str(r->params,"login");
char *token=json_param_str(r->params,"token");
char *ip=r->c->tcp_host;
err=user_tokin(login,token,ip);
if(err) goto exit;
USER_SESSION *us=user_session(login,token);
user_bind_session(r->c,us);
exit:
ns_rpc_response(r,err);
}
void api_user_get(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
char *login=json_str(r->params,"login");
USER *u=NULL;
if(login){
if(!api_is_admin(r)) return;
u=user(login);
}else{
u=api_user(r);
}
if(u){
JSTR *s=&temp_str;
jstr_reset(s);
user_get_json(u,s);
ns_rpc_response_raw_result(r,s->text,s->len);
}else{
ns_rpc_response_err(r,SERVER_ERROR_USER_NOT_FOUND);
}
}
void api_user_active(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
USER_SESSION *us=api_session(r);
user_active(us->login,us->token);
ns_rpc_response(r,0);
}
void api_user_close_session(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"tok")) return;
int err=0;
USER *u=api_user(r);
char *login=json_strd(r->params,"login");
char *tok=json_str(r->params,"tok");
if(login){
if(!api_is_admin(r)) return;
}else{
login=strdup(u->login);
}
if(!user_exists(login)){
err=SERVER_ERROR_USER_NOT_FOUND;
goto exit;
}
char *token=user_gettoken(login,tok);
if(!token){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
goto exit;
}
user_close_session(login,token);
exit:
jrnl(r,JRNL_SECURITY_CLOSE_SESSION,"object",login,NULL);
ns_rpc_response(r,err);
free(login);
}
void api_user_sessions(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
char *login=json_str(r->params,"login");
USER *u=api_user(r);
if(login){
if(!str_equal(login,u->login) && !api_is_admin(r)) return;
}else{
login=u->login;
}
if(user_exists(login)){
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_arr(s);
OBJ *ss=obj(user_get_sessions_path(login));
USER_SESSION *us;
obj_iter_type_bgn(ss,us,"session")
user_session_get_json(us,s);
obj_iter_type_end
jstr_cls_arr(s);
ns_rpc_response_raw_result(r,s->text,s->len);
}else{
ns_rpc_response_err(r,SERVER_ERROR_USER_NOT_FOUND);
}
}
void api_user_changepass(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"cur_password,new_password")) return;
USER_SESSION *us=api_session(r);
char *login=strdup(us->login);
char *token=strdup(us->token);
char *cur_password=json_str(r->params,"cur_password");
char *new_password=json_str(r->params,"new_password");
int err=user_change_password(login,cur_password,new_password,0);
if(err) goto exit;
user_close_sessions(login,token);
exit:
jrnl(r,JRNL_SECURITY_CHANGE_PASSWORD,"error",err,NULL);
ns_rpc_response(r,err);
free(login);
free(token);
}
void api_user_save_profile(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
if(!api_required(r,"login")) return;
if(!api_is_write_access(r)) return;
int err=0;
USER *u=api_user(r);
free(u->home_page);
free(u->home_project);
free(u->home_url);
free(u->icon);
free(u->name);
free(u->phone);
free(u->email);
free(u->language);
u->home_page=json_strd(r->params,"home_page");
u->home_project=json_strd(r->params,"home_project");
u->home_url=json_strd(r->params,"home_url");
u->icon=json_strd(r->params,"icon");
u->name=json_strd(r->params,"name");
u->language=json_strd(r->params,"language");
u->phone=json_strd(r->params,"phone");
u->email=json_strd(r->params,"email");
u->receive_email=json_bool(r->params,"receive_email");
u->receive_telegram=json_bool(r->params,"receive_telegram");
u->receive_sms=json_bool(r->params,"receive_sms");
err=user_save_user(u->o);
exit:
jrnl(r,JRNL_SECURITY_EDIT_PROFILE,"error",err,NULL);
ns_rpc_response(r,err);
}
void api_user_list(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_arr(s);
USER *u;
obj_iter_type_bgn(obj("/users"),u,"user")
user_get_json(u,s);
obj_iter_type_end
jstr_cls_arr(s);
ns_rpc_response_raw_result(r,s->text,s->len);
}
void api_user_save(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"cur_login,new_login")) return;
int block_event=0;
int err=0;
USER *u;
char *cur_login=json_str(r->params,"cur_login");
char *new_login=json_str(r->params,"new_login");
bool blocked=json_bool(r->params,"blocked");
bool admin=json_bool(r->params,"admin");
bool anonymous=(strcmp(cur_login,"anonymous")==0);
bool editor_access=json_bool(r->params,"editor_access");
if(anonymous){
if(admin || editor_access || (strcmp(new_login,cur_login)!=0)){
err=SERVER_ERROR_OPERATION_FAILED;
if(err) goto exit;
}
}
if(strcmp(cur_login,new_login)!=0){
if(user_exists(new_login)){
err=SERVER_ERROR_USER_EXISTS;
goto exit;
}
}
u=user(cur_login);
if(!u) err=SERVER_ERROR_USER_NOT_FOUND;
if(err) goto exit;
if(!u->blocked && blocked){
block_event=JRNL_SECURITY_BLOCK_USER;
}else if(u->blocked && !blocked){
block_event=JRNL_SECURITY_UNBLOCK_USER;
}
free(u->home_page);
free(u->home_project);
free(u->home_url);
free(u->icon);
free(u->name);
free(u->department);
free(u->apikey);
free(u->position);
free(u->language);
free(u->info);
free(u->phone);
free(u->email);
u->home_page=json_strd(r->params,"home_page");
u->home_project=json_strd(r->params,"home_project");
u->home_url=json_strd(r->params,"home_url");
u->icon=json_strd(r->params,"icon");
u->name=json_strd(r->params,"name");
u->language=json_strd(r->params,"language");
u->department=json_strd(r->params,"department");
u->apikey=json_strd(r->params,"apikey");
u->position=json_strd(r->params,"position");
u->info=json_strd(r->params,"info");
u->phone=json_strd(r->params,"phone");
u->email=json_strd(r->params,"email");
u->admin=json_bool(r->params,"admin");
u->blocked=json_bool(r->params,"blocked");
u->readonly=json_bool(r->params,"readonly");
u->changepass=json_bool(r->params,"changepass");
u->receive_email=json_bool(r->params,"receive_email");
u->receive_telegram=json_bool(r->params,"receive_telegram");
u->receive_sms=json_bool(r->params,"receive_sms");
u->kiosk_mode=json_bool(r->params,"kiosk_mode");
u->editor_access=json_bool(r->params,"editor_access");
err=user_save_user(u->o);
if(strcmp(cur_login,new_login)!=0){
USER_SESSION *us=api_session(r);
user_close_sessions(cur_login,us->token);
err=user_rename(cur_login,new_login);
if(strcmp(us->login,new_login)==0){
free(r->c->fn_data);
r->c->fn_data=strdup(obj_path(us->o));
}
if(err) goto exit;
}
exit:
jrnl(r,JRNL_SECURITY_EDIT_USER,"object",new_login,"error",err,NULL);
if(!err){
if(block_event==JRNL_SECURITY_BLOCK_USER){
USER_SESSION *us=api_session(r);
jrnl(NULL,JRNL_SECURITY_BLOCK_USER,"ip",us->ip,"executor",us->login,"object",new_login,"error",err,NULL);
user_close_sessions(cur_login,NULL);
user_close_sessions(new_login,NULL);
}else if(block_event==JRNL_SECURITY_UNBLOCK_USER){
USER_SESSION *us=api_session(r);
jrnl(NULL,JRNL_SECURITY_UNBLOCK_USER,"ip",us->ip,"executor",us->login,"object",new_login,"error",err,NULL);
}
}
ns_rpc_response(r,err);
}
void api_user_create(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"login,password")) return;
int err=0;
char *login=json_str(r->params,"login");
char *password=json_str(r->params,"password");
if(strcmp(login,"anonymous")==0) err=SERVER_ERROR_OPERATION_FAILED;
if(err) goto exit;
err=user_create(login);
if(err) goto exit;
err=user_change_password(login,NULL,password,0);
if(err) goto exit;
USER *u=user(login);
u->admin=json_bool(r->params,"admin");
u->blocked=json_bool(r->params,"blocked");
u->readonly=json_bool(r->params,"readonly");
u->changepass=json_bool(r->params,"changepass");
u->home_page=json_strd(r->params,"home_page");
u->home_project=json_strd(r->params,"home_project");
u->home_url=json_strd(r->params,"home_url");
u->icon=json_strd(r->params,"icon");
u->name=json_strd(r->params,"name");
u->language=json_strd(r->params,"language");
u->department=json_strd(r->params,"department");
u->apikey=json_strd(r->params,"apikey");
u->position=json_strd(r->params,"position");
u->info=json_strd(r->params,"info");
u->phone=json_strd(r->params,"phone");
u->email=json_strd(r->params,"email");
u->receive_email=json_bool(r->params,"receive_email");
u->receive_telegram=json_bool(r->params,"receive_telegram");
u->receive_sms=json_bool(r->params,"receive_sms");
u->kiosk_mode=json_bool(r->params,"kiosk_mode");
u->editor_access=json_bool(r->params,"editor_access");
err=user_save_user(u->o);
exit:
jrnl(r,JRNL_SECURITY_CREATE_USER,"object",login,"error",err,NULL);
ns_rpc_response(r,err);
}
void api_user_block(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"login")) return;
int err=0;
char *login=json_str(r->params,"login");
USER *u=api_user(r);
if(strcmp(login,u->login)==0) err=SERVER_ERROR_BLOCK_SELF;
if(err) goto exit;
err=user_block(login);
if(err) goto exit;
user_close_sessions(login,NULL);
exit:
jrnl(r,JRNL_SECURITY_BLOCK_USER,"object",login,"error",err,NULL);
ns_rpc_response(r,err);
}
void api_user_unblock(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"login")) return;
int err=0;
char *login=json_str(r->params,"login");
err=user_unblock(login);
if(err) goto exit;
exit:
jrnl(r,JRNL_SECURITY_UNBLOCK_USER,"object",login,"error",err,NULL);
ns_rpc_response(r,err);
}
void api_user_logout(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
int err=0;
USER_SESSION *us=api_session(r);
char *login=strdup(us->login);
char *token=strdup(us->token);
char *browser=strdup(us->browser);
err=user_logout(login,token);
if(err) goto exit;
exit:
jrnl(r,JRNL_SECURITY_USER_LOGOUT,"executor",login,"error",err,"data",str("{\"browser\":\"%s\"}",browser),NULL);
ns_rpc_response(r,err);
free(login);
free(browser);
free(token);
}
void api_fdb_prototype_nodes(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
int ok=acs(u,path,ACS_TYPE_VIEW,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
char *sp=prj_short_path(path);
char *project_path=prj_path(path);
OBJ *objects=obj(fdb_children_path(project_path,"nodes"));
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_arr(s);
OBJ *o;
obj_iter_all_children_bgn(objects,o)
JSON *p=obj_doc_json(o,"@prop.json");
if(p){
JSON *t=json_tok(p,"prototype");
if(t && str_equal(json_tos(t),sp)){
if(acs(u,o->fo->path,ACS_TYPE_VIEW,1)){
//obj_get_object_json(s,o,NULL,0,0,0,0,NULL,0,0);
jstr_opn_obj(s);
jstr_akey_ustr(s,"path",0,o->fo->path,0);
jstr_akey_ustr(s,"type",0,o->type,0);
jstr_akey_ustr(s,"icon",0,o->icon,0);
jstr_akey_int(s,"inactive",0,o->inactive);
jstr_cls_obj(s);
}
}
}
obj_iter_all_children_end
jstr_cls_arr(s);
exit:
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_raw_result(r,s->text,s->len);
}
}
void api_fdb_mimic_objects(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
int ok=acs(u,path,ACS_TYPE_VIEW,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
char *sp=prj_short_path(path);
char *project_path=prj_path(path);
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_arr(s);
{
OBJ *objects=obj(fdb_children_path(project_path,"screens"));
OBJ *o;
obj_iter_all_children_bgn(objects,o)
JSON *p=obj_doc_json(o,"@prop.json");
if(p){
{
JSON *t=json_tok(p,"desktop_mimic");
if(t && str_equal(json_tos(t),sp)){
if(acs(u,o->fo->path,ACS_TYPE_VIEW,1)){
jstr_opn_obj(s);
jstr_akey_ustr(s,"path",0,o->fo->path,0);
jstr_akey_ustr(s,"type",0,o->type,0);
jstr_akey_ustr(s,"icon",0,o->icon,0);
jstr_akey_int(s,"inactive",0,o->inactive);
jstr_cls_obj(s);
}
}
}
{
JSON *t=json_tok(p,"mobile_mimic");
if(t && str_equal(json_tos(t),sp)){
if(acs(u,o->fo->path,ACS_TYPE_VIEW,1)){
jstr_opn_obj(s);
jstr_akey_ustr(s,"path",0,o->fo->path,0);
jstr_akey_ustr(s,"type",0,o->type,0);
jstr_akey_ustr(s,"icon",0,o->icon,0);
jstr_akey_int(s,"inactive",0,o->inactive);
jstr_cls_obj(s);
}
}
}
}
obj_iter_all_children_end
}
{
OBJ *objects=obj(fdb_children_path(project_path,"prototypes"));
OBJ *o;
obj_iter_all_children_bgn(objects,o)
JSON *p=obj_doc_json(o,"@prop.json");
if(p){
{
JSON *t=json_tok(p,"desktop_mimic");
if(t && str_equal(json_tos(t),sp)){
if(acs(u,o->fo->path,ACS_TYPE_VIEW,1)){
jstr_opn_obj(s);
jstr_akey_ustr(s,"path",0,o->fo->path,0);
jstr_akey_ustr(s,"type",0,o->type,0);
jstr_akey_ustr(s,"icon",0,o->icon,0);
jstr_akey_int(s,"inactive",0,o->inactive);
jstr_cls_obj(s);
}
}
}
{
JSON *t=json_tok(p,"mobile_mimic");
if(t && str_equal(json_tos(t),sp)){
if(acs(u,o->fo->path,ACS_TYPE_VIEW,1)){
jstr_opn_obj(s);
jstr_akey_ustr(s,"path",0,o->fo->path,0);
jstr_akey_ustr(s,"type",0,o->type,0);
jstr_akey_ustr(s,"icon",0,o->icon,0);
jstr_akey_int(s,"inactive",0,o->inactive);
jstr_cls_obj(s);
}
}
}
}
obj_iter_all_children_end
}
jstr_cls_arr(s);
exit:
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_raw_result(r,s->text,s->len);
}
}
void api_fdb_bundle(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
JSON *ext=json_tok(r->params,"ext");
if(!obj_exists(path)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
int ok=acs(u,path,ACS_TYPE_VIEW,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_arr(s);
OBJ *parent=obj(path);
if(parent->fo->children){
OBJ *o;
obj_iter_all_children_bgn(parent,o)
char *path=obj_path(o);
bool ok=1;
if(ext && ok){
char *name=file_name(path);
char *oe=file_ext(name);
ok=0;
//printf("\n\n%s [%s]\n\n",path,oe);
if(ext->type==JSON_TYPE_STRING){
ok=str_cmp(oe,json_tos(ext))==0;
}else if(ext->type==JSON_TYPE_ARRAY){
int i;
char *e;
json_iter_array_str_bgn(ext,i,e)
ok=str_cmp(oe,e)==0;
if(ok) break;
json_iter_array_str_end
}
}
if(ok){
jstr_opn_obj(s);
jstr_akey_ustr(s,"file",0,path,0);
if(acs(u,path,ACS_TYPE_VIEW,1)){
void *data;
int64_t size;
FDB_OBJ *o=fdb_get_obj(&fdb,path);
if(o){
int err=fdb_read_doc(&fdb,o,"@content",&data,&size);
if(err){
jstr_akey_int(s,"error",0,err);
}else{
jstr_akey_ustr(s,"data",0,data,size);
}
}
}else{
jstr_akey_int(s,"error",0,SERVER_ERROR_ACCESS_DENIED);
}
jstr_cls_obj(s);
}
obj_iter_all_children_end
}else{
void *data;
int64_t size;
FDB_OBJ *o=fdb_get_obj(&fdb,path);
if(o){
jstr_opn_obj(s);
fdb_read_doc(&fdb,o,"@content",&data,&size);
jstr_akey_ustr(s,"file",0,path,0);
jstr_akey_ustr(s,"data",0,data,size);
jstr_cls_obj(s);
}
}
jstr_cls_arr(s);
exit:
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_raw_result(r,s->text,s->len);
}
}
void api_fdb_paths(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
JSON *ext=json_tok(r->params,"ext");
JSON *type=json_tok(r->params,"type");
bool dirs=json_bool(r->params,"dirs");
bool root=json_bool(r->params,"root");
if(!obj_exists(path)){
//printf("\n\n%s\n\n",path);
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
int ok=acs(u,path,ACS_TYPE_VIEW,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_arr(s);
if(root){
int len=strlen(path);
if(path[len-1]=='/'){
jstr_ustr(s,path,len-1);
}else{
jstr_ustr(s,path,len);
}
}
OBJ *parent=obj(path);
OBJ *o;
obj_iter_all_children_bgn(parent,o)
char *path=obj_path(o);
bool ok=1;
if(ext && ok){
char *name=file_name(path);
char *oe=file_ext(name);
ok=0;
//printf("\n\n%s [%s]\n\n",path,oe);
if(dirs && !oe[0]){
ok=1;
}else if(ext->type==JSON_TYPE_STRING){
ok=str_cmp(oe,json_tos(ext))==0;
}else if(ext->type==JSON_TYPE_ARRAY){
int i;
char *e;
json_iter_array_str_bgn(ext,i,e)
ok=str_cmp(oe,e)==0;
if(ok) break;
json_iter_array_str_end
}
}
if(type && ok){
ok=0;
if(type->type==JSON_TYPE_STRING){
ok=str_cmp(o->type,json_tos(type))==0;
}else if(type->type==JSON_TYPE_ARRAY){
int i;
char *t;
json_iter_array_str_bgn(type,i,t)
ok=str_cmp(o->type,t)==0;
if(ok) break;
json_iter_array_str_end
}
}
if(ok && acs(u,path,ACS_TYPE_VIEW,1)){
jstr_ustr(s,path,0);
}
obj_iter_all_children_end
jstr_cls_arr(s);
exit:
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_raw_result(r,s->text,s->len);
}
}
void api_fdb_search(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
USER *u=api_user(r);
char *path=json_str(r->params,"path");
char *search=json_str(r->params,"search");
if(!path) path="/projects";
char *docs[]={"@prop.json",NULL};
int count=0;
int more=0;
int max=1000;
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey(s,"list",0);
jstr_opn_arr(s);
if(search){
int sc=str_list_count(search," ");
char **ss=malloc(sc*sizeof(char*));
int i=0;
char *si;
str_list_iter_bgn(search," ",si)
ss[i++] = (char*) utf8_to_lower((unsigned char*)si);
str_list_iter_end
OBJ *o;
obj_iter_all_children_bgn(obj(path),o)
OBJ_TYPE *t=obj_schema_type(o->type);
if(!o->hidden && !o->inactive && t->interface){
char *path=obj_path(o);
bool ok=1;
if(ok && acs(u,path,ACS_TYPE_VIEW,1)){
JSON *prop=obj_doc_json(o,"@prop.json");
char *name=json_str(prop,"alias");
if(!name) name=obj_title(o);
char *lname = (char*) utf8_to_lower((unsigned char*)name);
ok=1;
for(int i=0; i=max){
more=max;
free(lname);
break;
}
obj_get_object_json(s,o,docs,0,1,0,0,u,0,0,1);
count++;
}
free(lname);
}
}
obj_iter_all_children_end
for(int i=0; itext,s->len);
}
void api_fdb_list(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
JSON *inactive=json_tok(r->params,"inactive");
JSON *docs=json_tok(r->params,"docs");
int children=json_int(r->params,"children");
int access=json_int(r->params,"access");
bool interface=json_bool(r->params,"interface");
int inact = inactive ? json_tob(inactive) : -1;
if(!obj_exists(path)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
int ok=acs(u,path,ACS_TYPE_VIEW,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
char **dd=NULL;
if(docs){
if(docs->type==JSON_TYPE_ARRAY){
dd=calloc(docs->count+1,sizeof(char*));
int i;
char *d;
json_iter_array_str_bgn(docs,i,d)
dd[i]=d;
json_iter_array_str_end
}else if(docs->type==JSON_TYPE_STRING){
dd=calloc(2,sizeof(char*));
dd[0]=json_tos(docs);
}
}
int parent_access=0;
if(access & ACS_TYPE_VIEW) parent_access+=acs(u,path,ACS_TYPE_VIEW,1);
if(access & ACS_TYPE_EDIT) parent_access+=acs(u,path,ACS_TYPE_EDIT,1);
if(access & ACS_TYPE_EXEC) parent_access+=acs(u,path,ACS_TYPE_EXEC,1);
JSTR *s=&temp_str;
jstr_reset(s);
obj_get_list_json(s,path,dd,inact,interface,children,u,access,parent_access);
free(dd);
exit:
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_raw_result(r,s->text,s->len);
}
}
void api_fdb_access(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
int ret=0;
char *path=json_str(r->params,"path");
int access=json_int_def(r->params,"access",ACS_TYPE_VIEW);
OBJ *o=obj(path);
if(!o){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
goto exit;
}
ret=acs(u,path,access,1);
exit:
if(err){
ns_rpc_response_err(r,err);
}else{
ns_rpc_response_bool(r,ret);
}
}
void api_fdb_load(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
JSON *docs=json_tok(r->params,"docs");
bool parent=json_bool(r->params,"parent");
int children=json_int(r->params,"children");
int access=json_int(r->params,"access");
bool interface=json_bool(r->params,"interface");
JSON *inactive=json_tok(r->params,"inactive");
int inact = inactive ? json_tob(inactive) : -1;
if(!obj_exists(path)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
int ok=acs(u,path,ACS_TYPE_VIEW,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
char **dd=NULL;
if(docs){
if(docs->type==JSON_TYPE_ARRAY){
dd=calloc(docs->count+1,sizeof(char*));
int i;
char *d;
json_iter_array_str_bgn(docs,i,d)
dd[i]=d;
json_iter_array_str_end
}else if(docs->type==JSON_TYPE_STRING){
dd=calloc(2,sizeof(char*));
dd[0]=json_tos(docs);
}
}
char *parent_path=fdb_parent_path(path);
int parent_access=0;
if(access & ACS_TYPE_VIEW) parent_access+=acs(u,parent_path,ACS_TYPE_VIEW,1);
if(access & ACS_TYPE_EDIT) parent_access+=acs(u,parent_path,ACS_TYPE_EDIT,1);
if(access & ACS_TYPE_EXEC) parent_access+=acs(u,parent_path,ACS_TYPE_EXEC,1);
JSTR *s=&temp_str;
jstr_reset(s);
obj_get_object_json(s,obj(path),dd,inact,interface,parent,children,u,access,parent_access,0);
free(dd);
exit:
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_raw_result(r,s->text,s->len);
}
}
void api_fdb_save(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
if(prj_building){
err=SERVER_ERROR_BUILDING_IN_PROGRESS;
goto exit;
}
if(!obj_check_editor_hold(path,u->login)){
err=SERVER_ERROR_EDITOR_HOLD_OBJECT;
goto exit;
}
if(!obj_exists(path)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
bool ok=acs(u,path,ACS_TYPE_EDIT,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
err=SERVER_ERROR_EDIT_ACCESS_DENIED;
goto exit;
}
OBJ *o=obj(path);
err=obj_validate(OBJ_METHOD_WRITE,o->fo->path,r->params);
if(err) goto exit;
char *k;
JSON *t;
json_iter_object_bgn(r->params,k,t)
if(k[0]=='@'){
char *format=json_str(t,"format");
JSON *data=json_tok(t,"data");
if(str_cmp(format,"json")==0){
int len;
char *text=json_stringify_buf(&temp_json_buffer,data,&len);
err=obj_write_with_check_access(o,k,text,len,u,&err_desc);
if(err) goto exit;
}else if(str_cmp(format,"text")==0){
char *text=json_tos(data);
int len=json_tol(data);
err=obj_write_with_check_access(o,k,text,len,u,&err_desc);
if(err) goto exit;
}else if(str_cmp(format,"base64")==0){
char *text=json_tos(data);
int size=json_tol(data);
int len;
void *bytes=str_base64_decode((unsigned char*)text,size,&len);
err=obj_write_with_check_access(o,k,bytes,len,u,&err_desc);
free(bytes);
}
}
json_iter_object_end
exit:
{
char *project=prj_name(path);
char *object=prj_pseudo_path(path,1);
jrnl(r,JRNL_PROJECT_WRITE_DATA,"project",project,"object",object,"error",err,NULL);
}
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_true(r);
}
}
void api_fdb_save_doc(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"path,file,format")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
char *file=json_str(r->params,"file");
char *format=json_str(r->params,"format");
char *data=json_str(r->params,"data");
int size=json_size(r->params,"data");
if(prj_building){
err=SERVER_ERROR_BUILDING_IN_PROGRESS;
goto exit;
}
if(!obj_check_editor_hold(path,u->login)){
err=SERVER_ERROR_EDITOR_HOLD_OBJECT;
goto exit;
}
if(!obj_exists(path)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
bool ok=acs(u,path,ACS_TYPE_EDIT,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
err=SERVER_ERROR_EDIT_ACCESS_DENIED;
goto exit;
}
OBJ *o=obj(path);
if(strcmp(format,"base64")!=0) err=SERVER_ERROR_INVALID_FORMAT;
if(err) goto exit;
int len;
void *bytes=str_base64_decode((unsigned char*)data,size,&len);
err=obj_write_with_check_access(o,file,bytes,len,u,&err_desc);
free(bytes);
exit:
{
char *project=prj_name(path);
char *object=prj_pseudo_path(path,1);
jrnl(r,JRNL_PROJECT_WRITE_DATA,"project",project,"object",object,"error",err,NULL);
}
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_true(r);
}
}
void api_fdb_load_doc(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path,file")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
char *file=json_str(r->params,"file");
char *format=json_str_def(r->params,"format","base64");
if(!obj_exists(path)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
bool ok=acs(u,path,ACS_TYPE_VIEW,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
OBJ *o=obj(path);
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
void *data;
int64_t size;
err=fdb_read_doc(&fdb,o->fo,file,&data,&size);
if(err) goto exit;
if(strcmp(format,"base64")==0){
jstr_akey_astr(s,"format",0,"base64",0);
jstr_akey_base64(s,"data",0,data,size);
}else if(strcmp(format,"json")==0){
jstr_akey_astr(s,"format",0,"json",0);
jstr_akey_raw(s,"data",0,data,size);
}
jstr_cls_obj(s);
ns_rpc_response_raw_result(r,s->text,s->len);
exit:
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}
}
void api_fdb_list_doc(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
if(!obj_exists(path)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
bool ok=acs(u,path,ACS_TYPE_VIEW,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
OBJ *o=obj(path);
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_arr(s);
char *doc;
khash_iter_bgn(o->fo->docs,doc)
jstr_ustr(s,doc,0);
khash_iter_end
jstr_cls_arr(s);
exit:
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_raw_result(r,s->text,s->len);
}
}
void api_fdb_delete(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
if(prj_building){
err=SERVER_ERROR_BUILDING_IN_PROGRESS;
goto exit;
}
if(!obj_check_editor_hold(path,u->login)){
err=SERVER_ERROR_EDITOR_HOLD_OBJECT;
goto exit;
}
if(!obj_exists(path)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
bool ok=acs(u,path,ACS_TYPE_EDIT,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
err=SERVER_ERROR_EDIT_ACCESS_DENIED;
goto exit;
}
err=obj_validate(OBJ_METHOD_DELETE,path,r->params);
if(err) goto exit;
err=fdb_delete_obj(&fdb,path);
exit:
{
char *project=prj_name(path);
char *object=prj_pseudo_path(path,1);
jrnl(r,JRNL_PROJECT_DELETE_DATA,"project",project,"object",object,"error",err,NULL);
}
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_true(r);
}
}
void api_fdb_move(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"path,dest")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
char *dest=json_str(r->params,"dest");
bool strict=json_bool(r->params,"strict"); // return error if dest exists
if(prj_building){
err=SERVER_ERROR_BUILDING_IN_PROGRESS;
goto exit;
}
if(!obj_check_editor_hold(path,u->login)){
err=SERVER_ERROR_EDITOR_HOLD_OBJECT;
goto exit;
}
if(!obj_exists(path)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
{
bool ok=acs(u,path,ACS_TYPE_EDIT,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
err=SERVER_ERROR_EDIT_ACCESS_DENIED;
goto exit;
}
}
{
char *parent_path=fdb_parent_path(path);
bool ok=acs(u,parent_path,ACS_TYPE_EDIT,1);
if(!ok){
OBJ *ao=obj_access(parent_path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
err=SERVER_ERROR_EDIT_ACCESS_DENIED;
goto exit;
}
}
{
char *parent_path=fdb_parent_path(dest);
bool ok=acs(u,parent_path,ACS_TYPE_EDIT,1);
if(!ok){
OBJ *ao=obj_access(parent_path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
err=SERVER_ERROR_EDIT_ACCESS_DENIED;
goto exit;
}
}
if(obj_exists(dest)){
if(strict){
err=SERVER_ERROR_OBJECT_EXISTS;
goto exit;
}else{
dest=fdb_next_name(&fdb,dest);
}
}
err=obj_validate(OBJ_METHOD_DELETE,path,r->params);
if(err) goto exit;
err=obj_validate(OBJ_METHOD_CREATE,dest,r->params);
if(err) goto exit;
err=fdb_move_obj(&fdb,path,dest);
if(err) goto exit;
exit:
{
char *project=prj_name(dest);
char *object=prj_pseudo_path(dest,1);
jrnl(r,JRNL_PROJECT_WRITE_DATA,"project",project,"object",object,"error",err,NULL);
}
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_str(r,dest,0);
}
}
void api_fdb_upload(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
bool created=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
char *data=json_str(r->params,"data");
int size=json_size(r->params,"data");
bool folder=json_bool(r->params,"folder");
if(prj_building){
err=SERVER_ERROR_BUILDING_IN_PROGRESS;
goto exit;
}
if(!obj_check_editor_hold(path,u->login)){
err=SERVER_ERROR_EDITOR_HOLD_OBJECT;
goto exit;
}
char *parent_path=fdb_parent_path(path);
bool ok=acs(u,parent_path,ACS_TYPE_EDIT,1);
if(!ok){
OBJ *ao=obj_access(parent_path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
err=SERVER_ERROR_EDIT_ACCESS_DENIED;
goto exit;
}
//printf("\n\n%s %u\n\n",path,folder);
if(!obj_exists(path)){
if(folder){
err=fdb_create_dir(&fdb,path);
}else{
err=fdb_create_file(&fdb,path);
}
if(err) goto exit;
created=1;
}
OBJ *o=obj(path);
if(!folder){
int len=0;
void *bytes=str_base64_decode((unsigned char*)data,size,&len);
if(len){
err=obj_write(o,"@content",bytes,len);
}else{
char *f=fdb_abs_path(&fdb,path);
int rc=file_create(f);
if(rc!=0) err=errno;
}
free(bytes);
}
exit:
{
char *project=prj_name(path);
char *object=prj_pseudo_path(path,1);
jrnl(r,JRNL_PROJECT_WRITE_DATA,"project",project,"object",object,"error",err,NULL);
}
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
if(created){
ns_rpc_response_true(r);
}else{
ns_rpc_response_false(r);
}
}
}
void api_fdb_create(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
if(prj_building){
err=SERVER_ERROR_BUILDING_IN_PROGRESS;
goto exit;
}
if(obj_exists(path)){
err=SERVER_ERROR_OBJECT_ALREADY_EXISTS;
goto exit;
}
char *parent_path=fdb_parent_path(path);
bool ok=acs(u,parent_path,ACS_TYPE_EDIT,1);
if(!ok){
OBJ *ao=obj_access(parent_path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
err=SERVER_ERROR_EDIT_ACCESS_DENIED;
goto exit;
}
err=obj_validate(OBJ_METHOD_CREATE,path,r->params);
if(err) goto exit;
err=obj_create(path);
if(err) goto exit;
exit:
{
char *project=prj_name(path);
char *object=prj_pseudo_path(path,1);
jrnl(r,JRNL_PROJECT_WRITE_DATA,"project",project,"object",object,"error",err,NULL);
}
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_str(r,path,0);
}
}
void api_fdb_create_next(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
char *next=NULL;
if(prj_building){
err=SERVER_ERROR_BUILDING_IN_PROGRESS;
goto exit;
}
if(!obj_check_editor_hold(path,u->login)){
err=SERVER_ERROR_EDITOR_HOLD_OBJECT;
goto exit;
}
char *parent_path=fdb_parent_path(path);
bool ok=acs(u,parent_path,ACS_TYPE_EDIT,1);
if(!ok){
OBJ *ao=obj_access(parent_path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
err=SERVER_ERROR_EDIT_ACCESS_DENIED;
goto exit;
}
next=fdb_next_name(&fdb,path);
err=obj_validate(OBJ_METHOD_CREATE,next,r->params);
if(err) goto exit;
err=obj_create(next);
if(err) goto exit;
exit:
{
char *p=next ? next : path;
char *project=prj_name(p);
char *object=prj_pseudo_path(p,1);
jrnl(r,JRNL_PROJECT_WRITE_DATA,"project",project,"object",object,"error",err,NULL);
}
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_str(r,next,0);
}
}
void api_fdb_nextname(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
char *next=NULL;
char *parent_path=fdb_parent_path(path);
bool ok=acs(u,parent_path,ACS_TYPE_VIEW,1);
if(!ok){
OBJ *ao=obj_access(parent_path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
next=fdb_next_name(&fdb,path);
exit:
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_str(r,next,0);
}
}
void api_fdb_clone(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
char *next=NULL;
if(prj_building){
err=SERVER_ERROR_BUILDING_IN_PROGRESS;
goto exit;
}
char *parent_path=fdb_parent_path(path);
bool ok=acs(u,parent_path,ACS_TYPE_EDIT,1);
if(!ok){
OBJ *ao=obj_access(parent_path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
err=SERVER_ERROR_EDIT_ACCESS_DENIED;
goto exit;
}
next=fdb_next_name(&fdb,path);
err=obj_validate(OBJ_METHOD_CREATE,next,r->params);
if(err) goto exit;
err=fdb_copy_obj(&fdb,path,next);
if(err) goto exit;
exit:
{
char *p=next ? next : path;
char *project=prj_name(p);
char *object=prj_pseudo_path(p,1);
jrnl(r,JRNL_PROJECT_WRITE_DATA,"project",project,"object",object,"error",err,NULL);
}
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_str(r,next,0);
}
}
void api_fdb_copy(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"path,dest")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
char *dest=json_str(r->params,"dest");
bool strict=json_bool(r->params,"strict");
if(prj_building){
err=SERVER_ERROR_BUILDING_IN_PROGRESS;
goto exit;
}
if(!obj_exists(path)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
char *parent_path=fdb_parent_path(dest);
bool ok=acs(u,parent_path,ACS_TYPE_EDIT,1);
if(!ok){
OBJ *ao=obj_access(parent_path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
err=SERVER_ERROR_EDIT_ACCESS_DENIED;
goto exit;
}
if(obj_exists(dest)){
if(strict){
err=SERVER_ERROR_OBJECT_EXISTS;
goto exit;
}else{
dest=fdb_next_name(&fdb,dest);
}
}
err=obj_validate(OBJ_METHOD_CREATE,dest,r->params);
if(err) goto exit;
err=fdb_copy_obj(&fdb,path,dest);
if(err) goto exit;
exit:
{
char *project=prj_name(dest);
char *object=prj_pseudo_path(dest,1);
jrnl(r,JRNL_PROJECT_WRITE_DATA,"project",project,"object",object,"error",err,NULL);
}
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_str(r,dest,0);
}
}
void api_system_groups(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path"); // project path
OBJ *p=obj_project(path);
if(!p){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
char *ggpath=fdb_children_path(p->fo->path,"groups");
OBJ *gg=obj(ggpath);
if(!gg){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=ggpath;
goto exit;
}
bool ok=acs(u,obj_path(gg),ACS_TYPE_VIEW,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_arr(s);
USER_GROUP *ug;
obj_iter_type_bgn(gg,ug,"group")
jstr_ustr(s,ug->name,0);
obj_iter_type_end
jstr_cls_arr(s);
exit:
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_raw_result(r,s->text,s->len);
}
}
void api_system_access(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
JSON *inherit_view=NULL;
JSON *inherit_edit=NULL;
JSON *inherit_exec=NULL;
char *inherit_view_mode=NULL;
char *inherit_edit_mode=NULL;
char *inherit_exec_mode=NULL;
char *inherit_view_groups=NULL;
char *inherit_edit_groups=NULL;
char *inherit_exec_groups=NULL;
char *explicit_access=NULL;
char *path=json_str(r->params,"path");
char *parent=strdup(fdb_parent_path(path));
bool ok=acs(u,path,ACS_TYPE_VIEW,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_EDIT_ACCESS_DENIED;
goto exit;
}
OBJ *o=obj(path);
OBJ *inherit_view_ao=obj_access(parent,ACS_TYPE_VIEW);
OBJ *inherit_edit_ao=obj_access(parent,ACS_TYPE_EDIT);
OBJ *inherit_exec_ao=obj_access(parent,ACS_TYPE_EXEC);
char *inherit_view_path=obj_path(inherit_view_ao);
char *inherit_edit_path=obj_path(inherit_edit_ao);
char *inherit_exec_path=obj_path(inherit_exec_ao);
JSON *a=obj_doc_json(o,"@access.json");
explicit_access=json_stringify_buf(&temp_json_buffer,a,NULL);
if(inherit_view_ao){
JSON *a=obj_doc_json(inherit_view_ao,"@access.json");
inherit_view=json_tok(a,"view");
inherit_view_mode=json_str_def(inherit_view,"mode","allow");
inherit_view_groups=json_param_stringify(inherit_view,"groups");
if(!inherit_view_groups) inherit_view_groups=strdup("[]");
}
if(inherit_exec_ao){
JSON *a=obj_doc_json(inherit_exec_ao,"@access.json");
inherit_exec=json_tok(a,"exec");
inherit_exec_mode=json_str_def(inherit_exec,"mode","allow");
inherit_exec_groups=json_param_stringify(inherit_exec,"groups");
if(!inherit_exec_groups) inherit_exec_groups=strdup("[]");
}
if(inherit_edit_ao){
JSON *a=obj_doc_json(inherit_edit_ao,"@access.json");
inherit_edit=json_tok(a,"edit");
inherit_edit_mode=json_str_def(inherit_edit,"mode","allow");
inherit_edit_groups=json_param_stringify(inherit_edit,"groups");
if(!inherit_edit_groups) inherit_edit_groups=strdup("[]");
}
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey(s,"inherit",0);
jstr_opn_obj(s);
jstr_akey(s,"view",0);
jstr_opn_obj(s);
jstr_akey_ustr(s,"path",0,inherit_view_path,0);
jstr_akey_ustr(s,"mode",0,inherit_view_mode,0);
jstr_akey_raw(s,"groups",0,inherit_view_groups,0);
jstr_cls_obj(s);
jstr_akey(s,"exec",0);
jstr_opn_obj(s);
jstr_akey_ustr(s,"path",0,inherit_exec_path,0);
jstr_akey_ustr(s,"mode",0,inherit_exec_mode,0);
jstr_akey_raw(s,"groups",0,inherit_exec_groups,0);
jstr_cls_obj(s);
jstr_akey(s,"edit",0);
jstr_opn_obj(s);
jstr_akey_ustr(s,"path",0,inherit_edit_path,0);
jstr_akey_ustr(s,"mode",0,inherit_edit_mode,0);
jstr_akey_raw(s,"groups",0,inherit_edit_groups,0);
jstr_cls_obj(s);
jstr_cls_obj(s);
jstr_akey_raw(s,"explicit",0,explicit_access,0);
jstr_cls_obj(s);
exit:
free(parent);
free(inherit_view_groups);
free(inherit_edit_groups);
free(inherit_exec_groups);
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_raw_result(r,s->text,s->len);
}
}
void api_system_html_files(NS_RPC_REQUEST *r){
if(!api_required(r,"folder")) return;
char *folder=json_str(r->params,"folder");
char *dir=file_subpath(param_html_dir,folder);
if(dir){
JSTR s;
jstr_init(&s,256);
jstr_opn_arr(&s);
char *name;
char *path;
file_iter_bgn(dir,FILE_TYPE_ANY,name,path)
bool isdir=file_isdir(path);
jstr_opn_obj(&s);
jstr_akey_ustr(&s,"name",0,name,0);
if(!isdir) jstr_akey_int(&s,"size",0,file_size(path));
jstr_akey_astr(&s,"type",0,isdir?"dir":"file",0);
jstr_cls_obj(&s);
file_iter_end
jstr_cls_arr(&s);
ns_rpc_response_raw_result(r,s.text,s.len);
jstr_free(&s);
free(dir);
}else{
ns_rpc_response_err(r,SERVER_ERROR_OPERATION_FAILED);
}
}
void api_system_set_config(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_required(r,"config")) return;
if(!api_is_write_access(r)) return;
JSON *config=json_tok(r->params,"config");
char *rp=json_stringify_buf(&temp_json_buffer,config,NULL);
jrnl(r,JRNL_SYSTEM_SET_CONFIG,"data",rp,NULL);
char *service;
JSON *params;
json_iter_object_bgn(config,service,params)
char *config=str("%s/%s/config.cfg",path_services_dir,service);
CFG *cfg=cfg_open(config,NULL);
if(cfg){
int n=0;
char *param;
char *value;
json_iter_object_str_bgn(params,param,value)
if(cfg_exist(cfg,param)){
char *old=cfg_str(cfg,param,NULL);
if(str_cmp(old,value)!=0){
log(r->c->id, "- %s=%s",param,value);
cfg_set_str(cfg,param,value);
n++;
}
}
json_iter_object_str_end
if(n) cfg_save(cfg);
cfg_free(cfg);
// restart_service(service); // service will be restarted by supervisor on config update
}
json_iter_object_end
ns_rpc_response_true(r);
}
void api_system_reset_config(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_required(r,"service")) return;
if(!api_is_write_access(r)) return;
char *service=json_str(r->params,"service");
char *file=str("%s/%s/config.cfg",path_services_dir,service);
errno=0;
file_remove(file);
if(file_exists(file)){
ns_rpc_response(r,errno);
}else{
ns_rpc_response_true(r);
}
}
void api_system_check_config(NS_RPC_REQUEST *r){
if(!api_required(r,"service")) return;
if(!api_is_admin(r)) return;
char *service=json_str(r->params,"service");
char *file=str("%s/%s/config.cfg",path_services_dir,service);
if(file_exists(file)){
ns_rpc_response_true(r);
}else{
ns_rpc_response_false(r);
}
}
void api_ddos_forget(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_required(r,"ip")) return;
if(!api_is_write_access(r)) return;
JSON *ips=json_tok(r->params,"ip");
char *ip_str=json_stringify_buf(&temp_json_buffer,ips,NULL);
jrnl(r,JRNL_SYSTEM_DDOS_FORGET,"data",ip_str,NULL);
char *ip;
int i;
json_iter_array_str_bgn(ips,i,ip)
ns_ddos_forget(ip);
json_iter_array_str_end
ns_rpc_response_true(r);
ns_ddos_routine(1);
}
void api_ddos_block(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_required(r,"ip")) return;
if(!api_is_write_access(r)) return;
JSON *ips=json_tok(r->params,"ip");
char *ip_str=json_stringify_buf(&temp_json_buffer,ips,NULL);
jrnl(r,JRNL_SECURITY_BLOCK_IP,"data",ip_str,NULL);
char *ip;
int i;
json_iter_array_str_bgn(ips,i,ip)
ns_ddos_set_blocked(ip,1);
json_iter_array_str_end
ns_rpc_response_true(r);
}
void api_ddos_unblock(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_required(r,"ip")) return;
if(!api_is_write_access(r)) return;
JSON *ips=json_tok(r->params,"ip");
char *ip_str=json_stringify_buf(&temp_json_buffer,ips,NULL);
jrnl(r,JRNL_SECURITY_UNBLOCK_IP,"data",ip_str,NULL);
char *ip;
int i;
json_iter_array_str_bgn(ips,i,ip)
ns_ddos_set_blocked(ip,0);
json_iter_array_str_end
ns_rpc_response_true(r);
}
void api_schedule_list(NS_RPC_REQUEST *r){
// if(!api_is_user(r)) return;
// if(!api_required(r,"path")) return;
// USER *u=api_user(r);
// int err=0;
// char *path=json_str(r->params,"path");
// OBJ *p=obj(path);
// if(!p){
// err=SERVER_ERROR_OBJECT_NOT_FOUND;
// goto exit;
// }
// if(!acs(u,path,ACS_TYPE_VIEW,1)){
// err=SERVER_ERROR_ACCESS_DENIED;
// goto exit;
// }
// JSTR *s=&temp_str;
// jstr_reset(s);
// jstr_opn_arr(s);
// OBJ *ch;
// obj_iter_bgn(p,ch,NULL)
// printf("\n\n%s\n\n",ch->fo->name);
// JSON *content=obj_doc_json(ch,"@content.json");
// jstr_opn_obj(s);
// jstr_akey_ustr(s,"name",ch->fo->name);
// jstr_cls_obj(s);
// obj_iter_end
// jstr_cls_arr(s);
// exit:
// if(err){
// ns_rpc_response_err(r,err);
// }else{
// ns_rpc_response_raw_result(r,s->text,s->len);
// }
}
void api_editor_group_users(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
if(!api_required(r,"project")) return;
int err=0;
USER *user=api_user(r);
if(!user->editor_access){
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
char *project=json_str(r->params,"project");
char *pp=obj_path(obj_project(project));
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_arr(s);
USER *u;
obj_iter_type_bgn(obj("/users"),u,"user")
user_read_temp_groups(u,pp,1);
jstr_opn_obj(s);
jstr_akey_ustr(s,"login",0,u->login,0);
jstr_akey_ustr(s,"icon",0,u->icon,0);
jstr_akey_ustr(s,"name",0,u->name,0);
jstr_akey_ustr(s,"department",0,u->department,0);
jstr_akey_ustr(s,"position",0,u->position,0);
if(u->temp_groups && *u->temp_groups){
jstr_akey(s,"groups",0);
jstr_opn_arr(s);
char **ug=u->temp_groups;
while(*ug){
jstr_ustr(s,*ug,0);
ug++;
}
jstr_cls_arr(s);
}
jstr_cls_obj(s);
obj_iter_type_end
jstr_cls_arr(s);
exit:
if(err){
ns_rpc_response_err(r,err);
}else{
ns_rpc_response_raw_result(r,s->text,s->len);
}
}
void api_editor_hold_object(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
HOLD *h=NULL;
char *path=json_str(r->params,"path");
bool force=json_bool(r->params,"force");
if(str_start(path,"/projects/")){
if(!obj_exists(path)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
goto exit;
}
bool ok=acs(u,path,ACS_TYPE_EDIT,1);
if(ok){
h=obj_get_editor_hold(path);
if(h){
if(strcmp(h->user,u->login)==0){
h->time=time_clock();
}else{
if(force){
HOLD *x=NULL;
char *p=strdup(path);
while(p && strcmp(p,"/projects")!=0){
x=khash_get(holds,p);
file_parent(p);
if(x){
khash_delete(holds,x->path);
free(x->path);
free(x->user);
free(x);
};
}
free(p);
h=calloc(1,sizeof(HOLD));
h->path=strdup(path);
h->user=strdup(u->login);
h->time=time_clock();
khash_set(holds,h->path,h);
}
}
}else{
h=calloc(1,sizeof(HOLD));
h->path=strdup(path);
h->user=strdup(u->login);
h->time=time_clock();
khash_set(holds,h->path,h);
}
}
}
exit:
if(err){
ns_rpc_response_err(r,err);
}else{
if(h){
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_ustr(s,"path",0,h->path,0);
jstr_akey_ustr(s,"user",0,h->user,0);
jstr_cls_obj(s);
ns_rpc_response_raw_result(r,s->text,s->len);
}else{
ns_rpc_response_null(r);
}
}
}
void api_fdb_templates(NS_RPC_REQUEST *r){
if(!api_required(r,"dir")) return;
char *dir=json_str(r->params,"dir");
char *temp_path=file_subpath(file_here("templates"),dir);
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
char *name;
char *path;
file_iter_bgn(temp_path,FILE_TYPE_DIR,name,path)
char *info=file_subpath(path,"info.json");
char *json=file_read_text(info);
jstr_ukey_raw(s,name,0,json,0);
free(json);
free(info);
file_iter_end
jstr_cls_obj(s);
ns_rpc_response_raw_result(r,s->text,s->len);
free(temp_path);
}
void api_fdb_import_template(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"template,path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *template=json_str (r->params,"template");
char *path=json_str (r->params,"path");
char *name=json_str (r->params,"name");
char tp[PATH_MAX];
char *t=NULL;
char *fp=NULL;
if(prj_building){
err=SERVER_ERROR_BUILDING_IN_PROGRESS;
goto exit;
}
snprintf(tp,PATH_MAX,"%s/%s/%s",file_here("templates"),template,u->language);
if(!file_direxists(tp)){
snprintf(tp,PATH_MAX,"%s/%s/%s",file_here("templates"),template,param_language);
}
if(!file_direxists(tp)){
snprintf(tp,PATH_MAX,"%s/%s",file_here("templates"),template);
char *name;
char *path;
file_iter_bgn(tp,FILE_TYPE_DIR,name,path)
snprintf(tp,PATH_MAX,"%s/%s/%s",file_here("templates"),template,name);
break;
file_iter_end
}
char *tname;
char *tpath;
file_iter_bgn(tp,FILE_TYPE_DIR,tname,tpath)
t=strdup(tpath);
break;
file_iter_end
if(!t){
err=SERVER_ERROR_OPERATION_FAILED;
goto exit;
}
if(!file_exists(t)){
err_desc=t;
err=SERVER_ERROR_OBJECT_NOT_FOUND;
goto exit;
}
if(!obj_exists(path)){
err_desc=path;
err=SERVER_ERROR_OBJECT_NOT_FOUND;
goto exit;
}
if(!acs(u,path,ACS_TYPE_EDIT,1)){
err=SERVER_ERROR_ACCESS_DENIED;
OBJ *ao=obj_access(path,ACS_TYPE_EDIT);
if(ao) err_desc=ao->fo->path;
goto exit;
}
if(!obj_check_editor_hold(path,u->login)){
err=SERVER_ERROR_EDITOR_HOLD_OBJECT;
goto exit;
}
fp=obj_import(t,path,name,1,&err);
exit:
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_str(r,fp,0);
}
free(fp);
free(t);
}
void api_cb_fdb_import(NS_RPC_REQUEST *req, NS_RPC_RESPONSE *res, void *cb_data){
NS_RPC_REQUEST *r=cb_data;
int err=0;
if(res->error) err=json_int(res->error,"code");
ns_rpc_parse_outgoing_request(req);
char *project=prj_name(json_str(req->params,"payload/project"));
char *path=json_str(req->params,"payload/path");
jrnl(r,JRNL_PROJECT_START_IMPORT,"project",project,"error",err,"data",path,NULL);
ns_rpc_response_back(r,res);
}
void api_fdb_import(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"file,path,data")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *file=json_str (r->params,"file");
char *path=json_str (r->params,"path");
char *data=json_str (r->params,"data");
int size=json_size(r->params,"data");
char *project=prj_path(path);
char *unpack_command=NULL;
char src[PATH_MAX];
char dst[PATH_MAX];
char *dir=NULL;
unsigned char *decoded_data=NULL;
int32_t decoded_size;
if(prj_building){
err=SERVER_ERROR_BUILDING_IN_PROGRESS;
goto exit;
}
if(!acs(u,path,ACS_TYPE_EDIT,1)){
err=SERVER_ERROR_ACCESS_DENIED;
OBJ *ao=obj_access(path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
goto exit;
}
if(!obj_check_editor_hold(path,u->login)){
err=SERVER_ERROR_EDITOR_HOLD_OBJECT;
goto exit;
}
if(!str_end(file,".tgz")){
err=SERVER_ERROR_INVALID_FORMAT;
goto exit;
}
dir=strdup(file);
dir[strlen(dir)-4]='\0';
snprintf(src,PATH_MAX,"%s/%s",path_import_dir,file);
snprintf(dst,PATH_MAX,"%s/%s",path_import_dir,dir);
if(file_exists(src)){
err=SERVER_ERROR_OPERATION_IN_PROGRESS;
goto exit;
}
decoded_data=str_base64_decode((unsigned char*)data,size,&decoded_size);
file_write(src,(char*)decoded_data,decoded_size);
file_mkpath(dst,0640);
unpack_command=str_f("%s \"%s\" \"%s\"",file_here("unpack_backup.sh"),src,dst);
//printf("\n\n%s\n\n",unpack_command);
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_ustr(s,"command",0,unpack_command,0);
jstr_akey(s,"payload",0);
jstr_opn_obj(s);
jstr_akey_uint(s,"cid",0,r->c->id);
jstr_akey_ustr(s,"rid",0,r->id,0);
jstr_akey_ustr(s,"method",0,r->method,0);
jstr_akey_ustr(s,"project",0,project,0);
jstr_akey_ustr(s,"path",0,path,0);
jstr_akey_ustr(s,"dst",0,dst,0);
jstr_akey_ustr(s,"src",0,src,0);
jstr_cls_obj(s);
jstr_cls_obj(s);
ns_rpc_request(srv_exec->c,"async",s->text,s->len,api_cb_fdb_import,r);
exit:
if(err){
jrnl(r,JRNL_PROJECT_START_IMPORT,"project",project,"error",err,NULL);
ns_rpc_response_error(r,err,NULL,err_desc,0);
}
free(dir);
free(decoded_data);
free(unpack_command);
}
void api_cb_fdb_export(NS_RPC_REQUEST *req, NS_RPC_RESPONSE *res, void *cb_data){
NS_RPC_REQUEST *r=cb_data;
int err=0;
if(res->error) err=json_int(res->error,"code");
ns_rpc_parse_outgoing_request(req);
char *project=prj_name(json_str(req->params,"payload/project"));
char *paths=json_param_stringify(req->params,"payload/paths");
jrnl(r,JRNL_PROJECT_START_EXPORT,"project",project,"error",err,"data",paths,NULL);
ns_rpc_response_back(r,res);
free(paths);
}
void api_fdb_export(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
//if(!api_is_write_access(r)) return;
if(!api_required(r,"paths")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
JSON *paths=json_tok(r->params,"paths");
char *paths_str=json_stringify_buf(&temp_json_buffer,paths,NULL);
char *first=json_tos(paths+1);
char *project=prj_path(first);
char *pack_command=NULL;
char *res=NULL;
char src[PATH_MAX];
char dst[PATH_MAX+20];
char *name=NULL;
char time[40];
if(paths->count==0){
err=NS_RPC_ERROR_PARAMS;
goto exit;
}else if(paths->count==1){
char *p=strdup(first);
name=strdup(file_title(file_name(p)));
free(p);
}else{
char *p=file_parent_copy(first);
name=strdup(file_title(file_name(p)));
free(p);
}
uint32_t t=time_s();
t--;
next:
t++;
struct tm *ltime=time_local(t);
strftime(time,40,"%Y-%m-%d-%H-%M-%S",ltime);
snprintf(src,sizeof(src),"%s/%s-%s",path_export_dir,name,time);
if(file_direxists(src)) goto next;
file_mkpath(src,0640);
snprintf(dst,sizeof(dst),"%s.tgz",src);
//printf("\n\n%s\n\n",dst);
char *p;
int i;
json_iter_array_str_bgn(paths,i,p)
if(u->admin || acs(u,p,ACS_TYPE_EDIT,1)){
char *path=fdb_abs_path(&fdb,p);
file_copy_to_dir(path,src,1);
}
json_iter_array_str_end
pack_command=str_f("%s \"%s\" \"%s\"",file_here("pack_backup.sh"),dst,src);
char url[PATH_MAX];
snprintf(url,PATH_MAX,"/export/%s",file_name(dst));
res=str_of_str(url);
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_ustr(s,"command",0,pack_command,0);
jstr_akey(s,"payload",0);
jstr_opn_obj(s);
jstr_akey_uint(s,"cid",0,r->c->id);
jstr_akey_ustr(s,"rid",0,r->id,0);
jstr_akey_ustr(s,"method",0,r->method,0);
jstr_akey_ustr(s,"project",0,project,0);
jstr_akey_raw(s,"paths",0,paths_str,0);
jstr_akey_ustr(s,"result",0,res,0);
jstr_cls_obj(s);
jstr_cls_obj(s);
ns_rpc_request(srv_exec->c,"async",s->text,s->len,api_cb_fdb_export,r);
exit:
if(err){
jrnl(r,JRNL_PROJECT_START_EXPORT,"project",project,"error",err,"data",paths_str,NULL);
ns_rpc_response_error(r,err,NULL,err_desc,0);
}
free(pack_command);
free(name);
free(res);
}
void api_cb_backup_create(NS_RPC_REQUEST *req, NS_RPC_RESPONSE *res, void *cb_data){
NS_RPC_REQUEST *r=cb_data;
int err=0;
if(res->error) err=json_int(res->error,"code");
char *project=json_tos(r->params);
jrnl(r,JRNL_PROJECT_START_BACKUP,"project",project,"error",err,NULL);
ns_rpc_response_back(r,res);
}
void api_backup_create(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"project")) return;
USER *u=api_user(r);
int err=0;
char time[40];
char src[PATH_MAX];
char dst[PATH_MAX];
char *pack_command=NULL;
char *path=NULL;
char *err_desc=NULL;
char *project=json_str(r->params,"project");
path=str_f("/projects/%s.project",project);
if(!obj_exists(path)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
goto exit;
}
bool ok=acs(u,path,ACS_TYPE_EDIT,0);
if(!ok){
err_desc=path;
err=SERVER_ERROR_EDIT_ACCESS_DENIED;
goto exit;
}
uint32_t t=time_s();
t--;
next:
t++;
struct tm *ltime=time_local(t);
strftime(time,40,"%Y-%m-%d-%H-%M-%S",ltime);
snprintf(src,PATH_MAX,"%s/%s-%s",path_export_dir,project,time);
if(file_direxists(src)) goto next;
snprintf(dst,PATH_MAX,"%s/%s-%s.tgz",path_backups_dir,project,time);
if(file_exists(dst)){
err=SERVER_ERROR_OBJECT_EXISTS;
goto exit;
}
file_mkpath(src,0640);
int rc=file_copy_to_dir(fdb_abs_path(&fdb,path),src,1);
if(rc!=0){
err=errno;
goto exit;
}
pack_command=str_f("%s \"%s\" \"%s\"",file_here("pack_backup.sh"),dst,src);
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_ustr(s,"command",0,pack_command,0);
jstr_akey(s,"payload",0);
jstr_opn_obj(s);
jstr_akey_uint(s,"cid",0,r->c->id);
jstr_akey_ustr(s,"rid",0,r->id,0);
jstr_akey_ustr(s,"method",0,r->method,0);
jstr_akey_raw(s,"result",0,"true",0);
jstr_cls_obj(s);
jstr_cls_obj(s);
ns_rpc_request(srv_exec->c,"async",s->text,s->len,api_cb_backup_create,r);
exit:
if(err){
jrnl(r,JRNL_PROJECT_START_BACKUP,"project",project,"error",err,NULL);
ns_rpc_response_error(r,err,NULL,err_desc,0);
}
free(path);
free(pack_command);
}
void api_cb_backup_restore(NS_RPC_REQUEST *req, NS_RPC_RESPONSE *res, void *cb_data){
NS_RPC_REQUEST *r=cb_data;
int err=0;
if(res->error) err=json_int(res->error,"code");
ns_rpc_parse_outgoing_request(req);
char *project=json_str(req->params,"payload/project");
jrnl(r,JRNL_PROJECT_START_RESTORE,"project",project,"error",err,NULL);
ns_rpc_response_back(r,res);
}
void api_backup_restore(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"backup")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *backup=json_str (r->params,"backup");
char *unpack_command=NULL;
char *project=NULL;
char src[PATH_MAX];
char dst[PATH_MAX];
char *pp=NULL;
int len=strlen(backup);
if(prj_building){
err=SERVER_ERROR_BUILDING_IN_PROGRESS;
goto exit;
}
if(len<=24){
err=NS_RPC_ERROR_PARAMS;
goto exit;
}
project=strdup(backup);
project[len-24]=0;
pp=str_f("/projects/%s.project",project);
if(!acs(u,pp,ACS_TYPE_EDIT,1)){
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
snprintf(src,PATH_MAX,"%s/%s",path_backups_dir,backup);
if(!file_exists(src)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=src;
goto exit;
}
char *t=file_title_copy(backup);
snprintf(dst,PATH_MAX,"%s/%s",path_import_dir,t);
free(t);
if(file_exists(dst)){
err=SERVER_ERROR_OPERATION_IN_PROGRESS;
goto exit;
}
file_mkpath(dst,0640);
unpack_command=str_f("%s \"%s\" \"%s\"",file_here("unpack_backup.sh"),src,dst);
//printf("\n\n%s\n\n",unpack_command);
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_ustr(s,"command",0,unpack_command,0);
jstr_akey(s,"payload",0);
jstr_opn_obj(s);
jstr_akey_uint(s,"cid",0,r->c->id);
jstr_akey_ustr(s,"rid",0,r->id,0);
jstr_akey_ustr(s,"method",0,r->method,0);
jstr_akey_ustr(s,"project",0,project,0);
jstr_akey_ustr(s,"dst",0,dst,0);
jstr_akey_ustr(s,"src",0,src,0);
jstr_cls_obj(s);
jstr_cls_obj(s);
ns_rpc_request(srv_exec->c,"async",s->text,s->len,api_cb_backup_restore,r);
exit:
if(err){
jrnl(r,JRNL_PROJECT_START_RESTORE,"project",project,"error",err,NULL);
ns_rpc_response_error(r,err,NULL,err_desc,0);
}
free(pp);
free(project);
free(unpack_command);
}
void api_backup_list(NS_RPC_REQUEST *r){
if(!api_is_registered_user(r)) return;
//if(!api_required(r,"project")) return;
USER *u=api_user(r);
//int err=0;
char *project=json_str(r->params,"project");
jstr_reset(&temp_str);
jstr_opn_arr(&temp_str);
char *name;
char *path;
file_iter_bgn(path_backups_dir,FILE_TYPE_FILE,name,path)
int len=strlen(name);
if(len>24){
char *n=strdup(name);
char *p=n+len-24;
p[0]=0;
// printf("\n\n%s %s\n\n",n,p);
if(!project || strcmp(n,project)==0){
char *pp=str_f("/projects/%s.project",n);
if(u->admin || acs(u,pp,ACS_TYPE_EDIT,1)){
jstr_opn_obj(&temp_str);
jstr_akey_ustr(&temp_str,"name",0,name,0);
jstr_akey_uint(&temp_str,"size",0,file_size(path));
jstr_cls_obj(&temp_str);
}
free(pp);
}
free(n);
}
file_iter_end
jstr_cls_arr(&temp_str);
ns_rpc_response_raw_result(r,temp_str.text,temp_str.len);
}
void api_backup_delete(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"backup")) return;
USER *u=api_user(r);
int err=0;
char *path=NULL;
char *project=NULL;
char *pp=NULL;
char *backup=json_str(r->params,"backup");
int len=strlen(backup);
if(len<=24){
err=NS_RPC_ERROR_PARAMS;
goto exit;
}
project=strdup(backup);
project[len-24]=0;
pp=str_f("/projects/%s.project",project);
if(!acs(u,pp,ACS_TYPE_EDIT,1)){
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
path=str_f("%s/%s",path_backups_dir,backup);
//printf("\n\n%s -> %s\n\n",path,project);
if(!file_exists(path)){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
goto exit;
}
int rc=file_remove(path);
if(rc!=0) err=errno;
exit:
jrnl(r,JRNL_PROJECT_DELETE_BACKUP,"object",backup,"error",err,NULL);
ns_rpc_response(r,err);
free(path);
free(project);
free(pp);
}
void api_cb_editor_start_build(NS_RPC_REQUEST *req, NS_RPC_RESPONSE *res, void *cb_data){
NS_RPC_REQUEST *r=cb_data;
int err=0;
if(res->error) err=json_int(res->error,"code");
char *project=json_str(r->params,"project");
jrnl(r,JRNL_PROJECT_START_BUILD,"project",project,"error",err,NULL);
ns_rpc_response_back(r,res);
}
void api_editor_start_build(NS_RPC_REQUEST *r){
if(!api_is_write_access(r)) return;
if(!api_is_editor_access(r)) return;
//ns_rpc_request_proxy(srv_builder->c,"build_projects",r);
int len;
char *params=json_stringify_buf(&temp_json_buffer,r->params,&len);
ns_rpc_request(srv_builder->c,"build_projects",params,len,api_cb_editor_start_build,r);
}
void api_cb_editor_cancel_build(NS_RPC_REQUEST *req, NS_RPC_RESPONSE *res, void *cb_data){
NS_RPC_REQUEST *r=cb_data;
int err=0;
if(res->error) err=json_int(res->error,"code");
char *project=json_str(r->params,"project");
jrnl(r,JRNL_PROJECT_CANCEL_BUILD,"project",project,"error",err,NULL);
ns_rpc_response_back(r,res);
}
void api_editor_cancel_build(NS_RPC_REQUEST *r){
if(!api_is_write_access(r)) return;
if(!api_is_editor_access(r)) return;
int len;
char *params=json_stringify_buf(&temp_json_buffer,r->params,&len);
ns_rpc_request(srv_builder->c,"cancel",params,len,api_cb_editor_cancel_build,r);
}
void api_log_get_server_config(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
char *dir=file_here("..");
char *service;
char *path;
file_iter_bgn(dir,FILE_TYPE_DIR,service,path)
JSTR c;
jstr_init(&c,1024);
char file[PATH_MAX+20];
snprintf(file,sizeof(file),"%s/config.cfg",path);
cfg_get_config_json(file,&c);
JSON *j=json_read(c.text,c.len);
jstr_akey(s,service,0);
jstr_opn_obj(s);
JSON *t;
char *k;
json_iter_object_bgn(j,k,t)
if(str_equal(k,"enabled")) jstr_akey_astr(s,k,0,json_tos(t),0);
if(str_equal(k,"ENABLED")) jstr_akey_astr(s,k,0,json_tos(t),0);
if(str_equal(k,"logger_enabled")) jstr_akey_astr(s,k,0,json_tos(t),0);
if(str_equal(k,"logger_write")) jstr_akey_astr(s,k,0,json_tos(t),0);
if(str_equal(k,"LOG_ENABLED")) jstr_akey_astr(s,k,0,json_tos(t),0);
if(str_start(k,"log_")) jstr_akey_astr(s,k,0,json_tos(t),0);
json_iter_object_end
jstr_cls_obj(s);
json_free(j);
jstr_free(&c);
file_iter_end
jstr_cls_obj(s);
ns_rpc_response_raw_result(r,s->text,s->len);
}
void api_log_get_server_schema(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
char *dir=file_here("..");
char *service;
char *path;
file_iter_bgn(dir,FILE_TYPE_DIR,service,path)
JSTR c;
jstr_init(&c,1024);
char file[PATH_MAX+20];
snprintf(file,sizeof(file),"%s/config.shema",path);
cfg_get_schema_json(file,&c);
JSON *j=json_read(c.text,c.len);
jstr_akey(s,service,0);
jstr_opn_obj(s);
JSON *t;
char *k;
json_iter_object_bgn(j,k,t)
if(str_start(k,"log_")){
int size;
char *data=json_stringify_buf(&temp_json_buffer,t,&size);
jstr_akey_raw(s,k,0,data,size);
}
json_iter_object_end
jstr_cls_obj(s);
json_free(j);
jstr_free(&c);
file_iter_end
jstr_cls_obj(s);
ns_rpc_response_raw_result(r,s->text,s->len);
}
void api_log_get_gateway_config(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
GW *gw=gw_get_gw_by_path(path);
if(!acs(u,path,ACS_TYPE_VIEW,1)){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
if(!gw){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_astr(s,"mac",0,gw->mac,0);
jstr_akey_astr(s,"method",0,"get_config",0);
jstr_akey(s,"params",0);
jstr_opn_obj(s);
jstr_akey_astr(s,"part",0,"data",0);
jstr_akey(s,"param_names",0);
jstr_opn_arr(s);
{
char **p=gateway_log_coinfig_params;
while(*p){
jstr_astr(s,*p,0);
p++;
}
}
jstr_cls_arr(s);
jstr_akey(s,"services",0);
jstr_opn_arr(s);
{
char **p=gateway_log_config_services;
while(*p){
jstr_astr(s,*p,0);
p++;
}
}
jstr_cls_arr(s);
jstr_cls_obj(s);
jstr_cls_obj(s);
ns_rpc_request_back(srv_drv_gateway->c,"gateway_api",s->text,s->len,r);
exit:
if(err) ns_rpc_response_error(r,err,NULL,err_desc,0);
}
void api_log_get_gateway_schema(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
GW *gw=gw_get_gw_by_path(path);
if(!acs(u,path,ACS_TYPE_VIEW,1)){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
if(!gw){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_astr(s,"mac",0,gw->mac,0);
jstr_akey_astr(s,"method",0,"get_config",0);
jstr_akey(s,"params",0);
jstr_opn_obj(s);
jstr_akey_astr(s,"part",0,"schema",0);
jstr_akey(s,"param_names",0);
jstr_opn_arr(s);
{
char **p=gateway_log_coinfig_params;
while(*p){
jstr_astr(s,*p,0);
p++;
}
}
jstr_cls_arr(s);
jstr_akey(s,"services",0);
jstr_opn_arr(s);
{
char **p=gateway_log_config_services;
while(*p){
jstr_astr(s,*p,0);
p++;
}
}
jstr_cls_arr(s);
jstr_cls_obj(s);
jstr_cls_obj(s);
//printf("\n\n%s\n\n",s->text);
ns_rpc_request_back(srv_drv_gateway->c,"gateway_api",s->text,s->len,r);
exit:
if(err) ns_rpc_response_error(r,err,NULL,err_desc,0);
}
void api_log_set_gateway_config(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path,config")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
JSON *config=json_tok(r->params,"config");
GW *gw=gw_get_gw_by_path(path);
if(!acs(u,path,ACS_TYPE_EDIT,1)){
OBJ *ao=obj_access(path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
if(!gw){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_astr(s,"mac",0,gw->mac,0);
jstr_akey_astr(s,"method",0,"set_config",0);
jstr_akey(s,"params",0);
jstr_opn_obj(s);
char *k;
JSON *service;
json_iter_object_bgn(config,k,service)
bool match=0;
char **p=gateway_log_config_services;
while(*p){
if(str_match(k,*p)){
match=1;
break;
}
p++;
}
if(match){
jstr_akey(s,k,0);
jstr_opn_obj(s);
char *k;
JSON *v;
json_iter_object_bgn(service,k,v)
bool match=0;
char **p=gateway_log_coinfig_params;
while(*p){
if(str_match(k,*p)){
match=1;
break;
}
p++;
}
if(match){
jstr_akey_ustr(s,k,0,json_tos(v),0);
}
json_iter_object_end
jstr_cls_obj(s);
}
json_iter_object_end
jstr_cls_obj(s);
jstr_cls_obj(s);
ns_rpc_request_back(srv_drv_gateway->c,"gateway_api",s->text,s->len,r);
exit:
if(err) ns_rpc_response_error(r,err,NULL,err_desc,0);
}
void api_gateway_restart_service(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path,service")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
char *service=json_str(r->params,"service");
GW *gw=gw_get_gw_by_path(path);
if(!acs(u,path,ACS_TYPE_EDIT,1)){
OBJ *ao=obj_access(path,ACS_TYPE_EDIT);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
if(!gw){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_astr(s,"mac",0,gw->mac,0);
jstr_akey_astr(s,"method",0,"restart",0);
jstr_akey_ustr(s,"params",0,service,0);
jstr_cls_obj(s);
ns_rpc_request_back(srv_drv_gateway->c,"gateway_api",s->text,s->len,r);
exit:
if(err) ns_rpc_response_error(r,err,NULL,err_desc,0);
}
void api_cb_gateway_reset_secret(NS_RPC_REQUEST *req, NS_RPC_RESPONSE *res, void *cb_data){
NS_RPC_REQUEST *r=cb_data;
int err=0;
if(res->error) err=json_int(res->error,"code");
char *gateway=json_str(r->params,"mac");
jrnl(r,JRNL_GATEWAY_RESET_SECRET,"gateway",gateway,"error",err,NULL);
ns_rpc_response_back(r,res);
}
void api_gateway_reset_secret(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
int len;
char *params=json_stringify_buf(&temp_json_buffer,r->params,&len);
ns_rpc_request(srv_drv_gateway->c,"gateway_reset_secret",params,len,api_cb_gateway_reset_secret,r);
}
void api_cb_gateway_exec(NS_RPC_REQUEST *req, NS_RPC_RESPONSE *res, void *cb_data){
NS_RPC_REQUEST *r=cb_data;
int err=0;
if(res->error) err=json_int(res->error,"code");
char *gateway=json_str(r->params,"mac");
char *data=json_stringify_buf(&temp_json_buffer,r->params,NULL);
jrnl(r,JRNL_GATEWAY_EXEC,"gateway",gateway,"data",data,"error",err,NULL);
ns_rpc_response_back(r,res);
}
void api_gateway_exec(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
int len;
char *params=json_stringify_buf(&temp_json_buffer,r->params,&len);
ns_rpc_request(srv_drv_gateway->c,"gateway_exec",params,len,api_cb_gateway_exec,r);
}
void api_cb_gateway_reboot(NS_RPC_REQUEST *req, NS_RPC_RESPONSE *res, void *cb_data){
NS_RPC_REQUEST *r=cb_data;
int err=0;
if(res->error) err=json_int(res->error,"code");
char *gateway=json_str(r->params,"mac");
jrnl(r,JRNL_GATEWAY_REBOOT,"gateway",gateway,"error",err,NULL);
ns_rpc_response_back(r,res);
}
void api_gateway_reboot(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
int len;
char *params=json_stringify_buf(&temp_json_buffer,r->params,&len);
ns_rpc_request(srv_drv_gateway->c,"gateway_reboot",params,len,api_cb_gateway_reboot,r);
}
void api_gateway_info(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"path")) return;
USER *u=api_user(r);
int err=0;
char *err_desc=NULL;
char *path=json_str(r->params,"path");
GW *gw=gw_get_gw_by_path(path);
if(!acs(u,path,ACS_TYPE_VIEW,1)){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
if(!gw){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
err_desc=path;
goto exit;
}
JSTR *s=&temp_str;
jstr_reset(s);
gw_get_info_json(gw,s);
ns_rpc_response_raw_result(r,s->text,s->len);
exit:
if(err) ns_rpc_response_error(r,err,NULL,err_desc,0);
}
void api_gateway_macs(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_arr(s);
GW *gw;
khash_iter_bgn(gw_list,gw)
jstr_astr(s,gw->mac,0);
khash_iter_end
jstr_cls_arr(s);
ns_rpc_response_raw_result(r,s->text,s->len);
}
void api_license_add(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"key")) return;
char *key=json_str(r->params,"key");
int err=license_add(key);
if(!err) license_recalc();
ns_rpc_response(r,err);
}
void api_license_delete(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(!api_required(r,"key")) return;
char *key=json_str(r->params,"key");
int err=license_delete(key);
if(!err) license_recalc();
ns_rpc_response(r,err);
}
void api_license_keys(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
int lic_vars=0;
jstr_reset(&temp_str);
jstr_opn_obj(&temp_str);
jstr_akey(&temp_str,"keys",0);
jstr_opn_arr(&temp_str);
char *name;
char *path;
file_iter_bgn(path_license_dir,FILE_TYPE_FILE,name,path)
char key[54];
int err=license_read(name,key);
if(!err){
int vars=license_check(key);
if(vars){
lic_vars+=vars;
jstr_opn_obj(&temp_str);
jstr_akey_astr(&temp_str,"key",0,name,0);
jstr_akey_int(&temp_str,"vars",0,vars);
jstr_akey_astr(&temp_str,"status",0,"active",0);
jstr_akey_int(&temp_str,"added",0,file_modified(path));
jstr_cls_obj(&temp_str);
}
}
file_iter_end
jstr_cls_arr(&temp_str);
jstr_akey_int(&temp_str,"ttl_vars",0,stat_physical_vars_cnt);
jstr_akey_int(&temp_str,"lic_vars",0,lic_vars);
jstr_cls_obj(&temp_str);
ns_rpc_response_raw_result(r,temp_str.text,temp_str.len);
}
void api_system_restart_service(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(srv_supervisor->connected){
char *params=json_param_stringify(r->params,"service");
ns_rpc_request_back(srv_supervisor->c,"restart",params,0,r);
free(params);
}else{
ns_rpc_response_err(r,SERVER_ERROR_SUPERVISOR_OFFLINE);
}
}
void api_system_start_service(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(srv_supervisor->connected){
char *params=json_param_stringify(r->params,"service");
ns_rpc_request_back(srv_supervisor->c,"start",params,0,r);
free(params);
}else{
ns_rpc_response_err(r,SERVER_ERROR_SUPERVISOR_OFFLINE);
}
}
void api_system_stop_service(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
if(srv_supervisor->connected){
char *params=json_param_stringify(r->params,"service");
ns_rpc_request_back(srv_supervisor->c,"stop",params,0,r);
free(params);
}else{
ns_rpc_response_err(r,SERVER_ERROR_SUPERVISOR_OFFLINE);
}
}
void api_system_reboot(NS_RPC_REQUEST *r){
if(!api_is_admin(r)) return;
if(!api_is_write_access(r)) return;
reboot=1;
jrnl(r,JRNL_SYSTEM_REBOOT,NULL);
ns_rpc_response(r,0);
}
void api_system_check_cron(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"cron")) return;
char *cron=json_str(r->params,"cron");
uint64_t time=0;
cron_check(cron,&time);
ns_rpc_response_int(r,time);
}
void api_trends_read(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"vars")) return;
int err=0;
USER *u=api_user(r);
USER_GROUP **ugg=user_groups(u);
int len;
char *params=NULL;
JSON *vars=json_tok(r->params,"vars");
int i;
JSON *t;
json_iter_array_bgn(vars,i,t)
if(t->type==JSON_TYPE_ARRAY){
char *vn=json_tos(t+1);
int vi=drv_index_by_name(vn);
if(vi>=0){
if(!acs_var(u,ugg,vi,ACS_TYPE_VIEW)){
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
}
}
json_iter_array_end
params=json_stringify_buf(&temp_json_buffer,vars,&len);
ns_rpc_request_back(srv_trends->c,"read",params,len,r);
exit:
if(err) ns_rpc_response_err(r,err);
free(ugg);
}
void api_trends_log(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"vars")) return;
int err=0;
USER *u=api_user(r);
USER_GROUP **ugg=user_groups(u);
int len;
char *params=NULL;
JSON *vars=json_tok(r->params,"vars");
int i;
JSON *t;
json_iter_array_bgn(vars,i,t)
if(t->type==JSON_TYPE_ARRAY){
char *vn=json_tos(t+1);
int vi=drv_index_by_name(vn);
if(vi>=0){
if(!acs_var(u,ugg,vi,ACS_TYPE_VIEW)){
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
}
}
json_iter_array_end
params=json_stringify_buf(&temp_json_buffer,r->params,&len);
ns_rpc_request_back(srv_trends->c,"log",params,len,r);
exit:
if(err) ns_rpc_response_err(r,err);
free(ugg);
}
void api_trends_slice(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_required(r,"vars")) return;
int err=0;
USER *u=api_user(r);
USER_GROUP **ugg=user_groups(u);
int len;
char *params=NULL;
JSON *vars=json_tok(r->params,"vars");
int i;
JSON *t;
json_iter_array_bgn(vars,i,t)
if(t->type==JSON_TYPE_ARRAY){
char *vn=json_tos(t+1);
int vi=drv_index_by_name(vn);
if(vi>=0){
if(!acs_var(u,ugg,vi,ACS_TYPE_VIEW)){
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
}
}
json_iter_array_end
params=json_stringify_buf(&temp_json_buffer,r->params,&len);
ns_rpc_request_back(srv_trends->c,"slice",params,len,r);
exit:
if(err) ns_rpc_response_err(r,err);
free(ugg);
}
void api_project_info(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
USER *u=api_user(r);
if(!api_required(r,"path")) return;
int err=0;
char *err_desc=NULL;
char *path=prj_path(json_str(r->params,"path"));
bool ok=acs(u,path,ACS_TYPE_VIEW,1);
if(!ok){
OBJ *ao=obj_access(path,ACS_TYPE_VIEW);
err_desc=obj_path(ao);
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
OBJ *o=obj(path);
if(!o){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
goto exit;
}
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
PROJECT *p=o->payload;
if(p){
jstr_akey_int(s,"stat_nodes",0,p->stat_nodes);
jstr_akey_int(s,"stat_vars",0,p->stat_vars);
jstr_akey_int(s,"stat_virt_vars",0,p->stat_virt_vars);
jstr_akey_int(s,"stat_phis_vars",0,p->stat_phis_vars);
}
jstr_cls_obj(s);
exit:
if(err){
ns_rpc_response_error(r,err,NULL,err_desc,0);
}else{
ns_rpc_response_raw_result(r,s->text,s->len);
}
}
void api_var_get(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
USER *u=api_user(r);
USER_GROUP **ugg=user_groups(u);
JSON *vars=json_tok(r->params,"vars");
JSON *nodes=json_tok(r->params,"nodes");
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_arr(s);
if(vars){
if(vars->type==JSON_TYPE_ARRAY){
int i;
JSON *t;
json_iter_array_bgn(vars,i,t)
int vi=-1;
if(json_is_str(t)){
vi=drv_index_by_name(json_tos(t));
}else{
vi=json_toi(t);
}
if(drv_exists(vi) && acs_var(u,ugg,vi,ACS_TYPE_VIEW)){
drv_var_to_str(vi,s);
}else{
jstr_raw(s,"null",4);
}
json_iter_array_end
}else{
JSON *t=vars;
int vi=-1;
if(json_is_str(t)){
vi=drv_index_by_name(json_tos(t));
}else{
vi=json_toi(t);
}
if(drv_exists(vi) && acs_var(u,ugg,vi,ACS_TYPE_VIEW)){
drv_var_to_str(vi,s);
}else{
jstr_raw(s,"null",4);
}
}
}
if(nodes){
if(nodes->type==JSON_TYPE_ARRAY){
int i;
JSON *t;
json_iter_array_bgn(nodes,i,t)
char *node=json_tos(t);
VAR_NODE *n=NULL;
if(!n) n=khash_get(var_node_prefixes,node);
if(!n) n=khash_get(var_node_paths,node);
if(n && acs(u,n->path,ACS_TYPE_VIEW,1)){
for(int i=0; ivar_cnt; i++){
int vi=n->var_arr[i];
drv_var_to_str(vi,s);
}
}
json_iter_array_end
}else{
char *node=json_tos(nodes);
VAR_NODE *n=NULL;
if(!n) n=khash_get(var_node_prefixes,node);
if(!n) n=khash_get(var_node_paths,node);
if(n && acs(u,n->path,ACS_TYPE_VIEW,1)){
for(int i=0; ivar_cnt; i++){
int vi=n->var_arr[i];
drv_var_to_str(vi,s);
}
}
}
}
jstr_cls_arr(s);
free(ugg);
ns_rpc_response_raw_result(r,s->text,s->len);
}
void api_var_set(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!param_demo_mode && !api_is_write_access(r)) return;
if(!api_required(r,"var")) return;
JSON *tvalue=json_tok(r->params,"value");
char *var=json_str(r->params,"var");
double value=tvalue ? json_tod(tvalue) : DRV_UNDEFINED;
char *payload=json_param_stringify(r->params,"payload");
var_set(r,var,value,payload,JRNL_EXP_SET_VAR,0);
free(payload);
}
void api_var_info(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
int err=0;
char *var=json_str(r->params,"var");
int vi=drv_index_by_name(var);
VAR_DATA *vd=drv_var_data(vi);
VAR_NODE *n=drv_node_data(vd->nodeid);
if(!n){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
goto exit;
}
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
if(n->gateway && n->gateway[0]) jstr_akey_astr(s,"gateway",0,n->gateway,0);
if(drv_keys_vars){
JKR jkr;
jkr_init(&jkr,drv_keys_vars,vd->token);
int i;
char *k;
json_iter_array_str_bgn(drv_keys_vars,i,k)
JSON *t=jkr_tok(&jkr,vd->token,k);
int len;
char *str=json_stringify(t,&len);
if(str) jstr_akey_raw(s,k,0,str,len);
free(str);
json_iter_array_str_end
}
jstr_cls_obj(s);
ns_rpc_response_raw_result(r,s->text,s->len);
exit:
if(err) ns_rpc_response_err(r,err);
}
void api_node_prefixes(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
USER *u=api_user(r);
JSON *paths=json_tok(r->params,"paths");
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_arr(s);
int i;
char *path;
json_iter_array_str_bgn(paths,i,path)
VAR_NODE *n=khash_get(var_node_paths,path);
if(n && acs(u,n->path,ACS_TYPE_VIEW,1)){
jstr_astr(s,n->prefix,n->prefix_len);
}else{
jstr_astr(s,"null",0);
}
json_iter_array_str_end
jstr_cls_arr(s);
ns_rpc_response_raw_result(r,s->text,s->len);
}
void api_node_list(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
USER *u=api_user(r);
JSON *prefixes=json_tok(r->params,"prefixes");
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_raw(s,"keys",4,node_keys,0);
jstr_akey(s,"rows",4);
jstr_opn_arr(s);
int i;
char *prefix;
json_iter_array_str_bgn(prefixes,i,prefix)
VAR_NODE *n=khash_get(var_node_prefixes,prefix);
if(n){
if(acs(u,n->path,ACS_TYPE_VIEW,1)){
jstr_raw(s,n->json_str,n->json_len);
}
}
json_iter_array_str_end
jstr_cls_arr(s);
jstr_cls_obj(s);
ns_rpc_response_raw_result(r,s->text,s->len);
}
void api_var_list(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
USER *u=api_user(r);
USER_GROUP **ugg=NULL;
char *path=json_str(r->params,"path");
JSON *list=json_tok(r->params,"list");
bool alarms=json_bool(r->params,"alarms");
bool strict=json_bool(r->params,"strict"); // return var item or null if no exists
int *arr=NULL;
int cnt=0;
bool free_arr=0;
if(list){
char *project_prefix=NULL;
char project_prefix_buf[256];
int project_prefix_len=0;
char *node_prefix=NULL;
char node_prefix_buf[256];
int node_prefix_len=0;
if(path){
project_prefix=prj_prefix(prj_path(path));
project_prefix_len=strlen(project_prefix);
project_prefix_len=sprintf(project_prefix_buf,"%.*s_",project_prefix_len,project_prefix);
VAR_NODE *n=khash_get(var_node_paths,path);
if(n){
node_prefix=n->prefix;
node_prefix_len=sprintf(node_prefix_buf,"%.*s_",n->prefix_len,n->prefix);
}
}
char *v;
int i;
if(strict){
cnt=list->count;
}else{
json_iter_array_str_bgn(list,i,v)
int vi=drv_index_by_name(v);
if(vi<0 && project_prefix){
strlcpy(project_prefix_buf+project_prefix_len,v,sizeof(project_prefix_buf)-project_prefix_len);
vi=drv_index_by_name(project_prefix_buf);
}
if(vi<0 && node_prefix){
strlcpy(node_prefix_buf+node_prefix_len,v,sizeof(node_prefix_buf)-node_prefix_len);
vi=drv_index_by_name(node_prefix_buf);
}
if(vi>=0) cnt++;
json_iter_array_str_end
}
arr=malloc(cnt*sizeof(int));
cnt=0;
free_arr=1;
json_iter_array_str_bgn(list,i,v)
int vi=drv_index_by_name(v);
if(vi<0 && project_prefix){
strlcpy(project_prefix_buf+project_prefix_len,v,sizeof(project_prefix_buf)-project_prefix_len);
vi=drv_index_by_name(project_prefix_buf);
}
if(vi<0 && node_prefix){
strlcpy(node_prefix_buf+node_prefix_len,v,sizeof(node_prefix_buf)-node_prefix_len);
vi=drv_index_by_name(node_prefix_buf);
}
if(vi>=0 || strict) arr[cnt++]=vi;
json_iter_array_str_end
}else if(path){
if(alarms){
VEC *ap=khash_get(var_alarm_paths,path);
if(ap){
arr=ap->items;
cnt=ap->count;
}
}else{
char *ext=file_ext(path);
if(strcmp(ext,"node")==0 || strcmp(ext,"gateway")==0){
VAR_NODE *n=khash_get(var_node_paths,path);
if(n){
arr=n->var_arr;
cnt=n->var_cnt;
}
}else if(strcmp(ext,"project")==0){
int projectid=prj_id(path);
for(int i=0; iprojectid==projectid){
cnt+=n->var_cnt;
}
}
arr=malloc(cnt*sizeof(int));
cnt=0;
free_arr=1;
for(int i=0; iprojectid==projectid){
for(int i=0; ivar_cnt; i++){
int idx=n->var_arr[i];
arr[cnt++]=idx;
}
}
}
}
}
}else{
arr=var_index_arr;
cnt=var_count;
}
ugg=user_groups(u);
int nodes_cnt=0;
int nodes_cap=drv_nodes_count;
int *nodes_arr=calloc(nodes_cap,sizeof(int));
int nodeid=-1;
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey(s,"vars",4);
jstr_opn_obj(s);
jstr_akey_raw(s,"keys",4,var_keys,0);
jstr_akey(s,"rows",4);
jstr_opn_arr(s);
for(int i=0; i=0){
if(acs_var(u,ugg,vi,ACS_TYPE_VIEW)){
VAR_DATA *vd=drv_var_data(vi);
jstr_raw(s,vd->json_str,vd->json_len);
if(nodeid!=vd->nodeid){
nodeid=vd->nodeid;
if(nodes_cnt>=nodes_cap){
nodes_cap=nodes_cap*2;
nodes_arr=realloc(nodes_arr,nodes_cap*sizeof(int));
}
nodes_arr[nodes_cnt++]=vd->nodeid;
}
}
}else{
jstr_raw(s,NULL,0);
}
}
jstr_cls_arr(s);
jstr_cls_obj(s);
jstr_akey(s,"nodes",5);
jstr_opn_obj(s);
jstr_akey_raw(s,"keys",4,node_keys,0);
jstr_akey(s,"rows",4);
jstr_opn_arr(s);
for(int i=0; ijson_str,n->json_len);
}
jstr_cls_arr(s);
jstr_cls_obj(s);
jstr_cls_obj(s);
ns_rpc_response_raw_result(r,s->text,s->len);
free(nodes_arr);
if(free_arr) free(arr);
free(ugg);
}
void api_journal(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
USER *u=api_user(r);
int err=0;
bool access=u->admin;
if(!access){
JSON *filter=json_tok(r->params,"filter");
int i;
JSON *f;
json_iter_array_bgn(filter,i,f)
if(f && f->type==JSON_TYPE_ARRAY && f->count>=3){
char *param=json_tos(f+1);
char *comp=json_tos(f+2);
JSON *vals=f+3;
if(vals && vals->type==JSON_TYPE_ARRAY && vals->count==1){
char *val=json_tos(vals+1);
if(str_cmp(param,"project")==0 && str_cmp(comp,"LIKE")==0 && val){
char path[PATH_MAX];
snprintf(path,sizeof(path),"/projects/%s.project/journal",val);
access=acs(u,path,ACS_TYPE_VIEW,1);
goto exit;
}else if(str_cmp(param,"gateway")==0 && str_cmp(comp,"LIKE")==0 && val){
char *mac=val;
GW *gw=gw_get_gw(mac);
if(gw){
for(int i=0; ipaths.count; i++){
char *p = *(char**)vec(&gw->paths,i);
access=acs(u,p,ACS_TYPE_VIEW,1);
goto exit;
}
}
access=1;
}
}
}
json_iter_array_end
}
exit:
if(!access) err=SERVER_ERROR_ACCESS_DENIED;
if(err){
ns_rpc_response_err(r,err);
}else{
ns_rpc_request_proxy(srv_db->c,"journal_read",r);
}
}
void api_script_debug(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!api_is_write_access(r)) return;
ns_rpc_request_proxy(srv_script->c,"debug",r);
}
void api_alarm_ack(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!param_demo_mode && !api_is_write_access(r)) return;
if(!api_required(r,"var")) return;
USER *u=api_user(r);
char *ip=ns_rpc_get_remote_ip(r->c);
char *user=str_of_str(u->login);
char *var=json_str(r->params,"var");
int value=0x101;
char *payload=str_f("{\"us\":%s,\"ip\":\"%s\"}",user,ip);
var_set(r,var,value,payload,JRNL_EXP_ACK_ALARM,1);
free(payload);
free(user);
}
void api_alarm_unack(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!param_demo_mode && !api_is_write_access(r)) return;
if(!api_required(r,"var")) return;
USER *u=api_user(r);
char *ip=ns_rpc_get_remote_ip(r->c);
char *user=str_of_str(u->login);
char *var=json_str(r->params,"var");
int value=0x102;
char *payload=str_f("{\"us\":%s,\"ip\":\"%s\"}",user,ip);
var_set(r,var,value,payload,JRNL_EXP_UNACK_ALARM,1);
free(payload);
free(user);
}
void api_alarm_shelve(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!param_demo_mode && !api_is_write_access(r)) return;
if(!api_required(r,"var")) return;
USER *u=api_user(r);
char *ip=ns_rpc_get_remote_ip(r->c);
char *user=str_of_str(u->login);
char *var=json_str(r->params,"var");
int value=0x103;
uint32_t period=json_int(r->params,"period");
char *payload=str_f("{\"us\":%s,\"ip\":\"%s\",\"sh\":%u}",user,ip,period);
var_set(r,var,value,payload,JRNL_EXP_SHELVE_ALARM,1);
free(payload);
free(user);
}
void api_alarm_unshelve(NS_RPC_REQUEST *r){
if(!api_is_user(r)) return;
if(!param_demo_mode && !api_is_write_access(r)) return;
if(!api_required(r,"var")) return;
USER *u=api_user(r);
char *ip=ns_rpc_get_remote_ip(r->c);
char *user=str_of_str(u->login);
char *var=json_str(r->params,"var");
int value=0x104;
char *payload=str_f("{\"us\":%s,\"ip\":\"%s\"}",user,ip);
var_set(r,var,value,payload,JRNL_EXP_SHELVE_ALARM,1);
free(payload);
free(user);
}
void api_test(NS_RPC_REQUEST *r){
int err=0;
char *path=strdup("/projects/new.node");
char *parent=fdb_parent_path(path);
printf("\n\n%s %s\n\n",parent,path);
char *type=obj_type_ex(path,1);
printf("\n\n%s\n\n",type);
if(!type){
err=SERVER_ERROR_UNKNOWN_TYPE;
if(err) goto exit;
}
// if type ok then copy dir
FDB_OBJ *o=fdb_get_obj(&fdb,parent);
FDB_OBJ *ch=fdb_scan(&fdb,path,0);
if(ch){
ch->parent=o;
khash_set(o->children,ch->path,ch);
}
exit:
free(path);
ns_rpc_response(r,err);
}
void api_cb_db_count_notification(NS_RPC_REQUEST *req, NS_RPC_RESPONSE *res, void *cb_data){
char *skey=cb_data;
if(!res->error){
NS_RPC_SUBSCRIPTION *s=ns_rpc_get_subscription(skey);
if(s){
int len;
char *data=json_stringify_buf(&temp_json_buffer, res->result,&len);
ns_rpc_subscription_data(s,NULL,data,len);
}
}
free(skey);
}
void api_cb_user_notifications_subscribed(NS_RPC_SUBSCRIPTION *s){
USER *u=api_user_con(s->c);
USER_SESSION *us=api_session_con(s->c);
if(us && u && !u->anonymous){
char *tok=user_gettok(us->token);
char *params=str_f("{\"user\":\"%s\",\"tok\":\"%s\"}",u->login,tok);
ns_rpc_request(srv_db->c,"notification_count",params,0,api_cb_db_count_notification,strdup(s->key));
free(params);
}else{
ns_rpc_subscription_close(s,NULL,SERVER_ERROR_ACCESS_DENIED,NULL);
}
}
void api_cb_builder_status_event(NS_RPC_SUBSCRIPTION *rs, void *cb_data){
int len;
char *data=json_stringify_buf(&temp_json_buffer,rs->data,&len);
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_ustr(s,"action",0,"status",0);
jstr_akey_raw(s,"status",0,data,len);
jstr_cls_obj(s);
ns_rpc_subscription_data(NULL,"builder",s->text,s->len);
//printf("\n\n%s %u\n\n","builder status",s->len);
}
void api_cb_builder_signal_event(NS_RPC_SUBSCRIPTION *rs, void *cb_data){
char *data=json_tos(rs->data);
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_ustr(s,"action",0,"signal",0);
jstr_akey_ustr(s,"signal",0,data,0);
jstr_cls_obj(s);
ns_rpc_subscription_data(NULL,"builder",s->text,s->len);
//printf("\n\n%s %s\n\n","builder signal",s->text);
if(str_cmp(data,"building_vars_started")==0){
prj_building=1;
}else if(str_cmp(data,"building_vars_finished")==0){
prj_building=0;
// acs_clear_cache();
// prj_reload_vars();
drv_load_vars();
gw_reload_list();
prj_need_build(0);
prj_need_refresh(1);
prj_update_objects_data();
user_invalidate_groups();
// var_unload();
// var_upload();
}
}
void api_cb_builder_subscribed(NS_RPC_SUBSCRIPTION *s){
USER *u=api_user_con(s->c);
if(u && u->editor_access){
// ok
prj_need_build_update(u);
}else{
ns_rpc_subscription_close(s,NULL,SERVER_ERROR_ACCESS_DENIED,NULL);
}
}
void api_cb_alarms_subscribed(NS_RPC_SUBSCRIPTION *s){
USER *u=api_user_con(s->c);
if(u){
alarm_process_subscription(s,1);
}else{
ns_rpc_subscription_close(s,NULL,SERVER_ERROR_ACCESS_DENIED,NULL);
}
}
void api_cb_user_update_subscribed(NS_RPC_SUBSCRIPTION *s){
char *login=json_str(s->options,"login");
USER *u=api_user_con(s->c);
if(u && (api_is_admin_con(s->c) || str_equal(login,u->login))){
// ok
}else{
ns_rpc_subscription_close(s,NULL,SERVER_ERROR_ACCESS_DENIED,NULL);
}
}
void api_cb_license_subscribed(NS_RPC_SUBSCRIPTION *s){
license_update_subscriptions(s);
}
void api_cb_session_update_subscribed(NS_RPC_SUBSCRIPTION *s){
char *login=json_str(s->options,"login");
USER *u=api_user_con(s->c);
if(api_is_admin_con(s->c) || str_equal(login,u->login)){
// ok
}else{
ns_rpc_subscription_close(s,NULL,SERVER_ERROR_ACCESS_DENIED,NULL);
}
}
void api_cb_log_event(NS_RPC_SUBSCRIPTION *rs, void *cb_data){
int len;
if(rs->error){
int code=json_int(rs->error,"code");
char *message=json_str(rs->error,"message");
ns_rpc_subscription_close(NULL,"log",code,message);
}else{
char *data=json_stringify_buf(&temp_json_buffer,rs->data,&len);
ns_rpc_subscription_data(NULL,"log",data,len);
}
}
void api_subscribe_log(){
ns_rpc_api_log_next_subscription("event","$events","data");
ns_rpc_subscribe(srv_log_viewer->c,"log",NULL,NULL,0,api_cb_log_event,NULL);
}
void api_unsubscribe_log(){
ns_rpc_api_log_next_subscription("event","$events","data");
ns_rpc_unsubscribe(srv_log_viewer->c,"log",NULL,NULL,0,api_cb_log_event,NULL);
}
void api_cb_log_subscribed(NS_RPC_SUBSCRIPTION *s){
if(api_is_admin_con(s->c)){
if(ns_rpc_subscription_count("log")==1) api_subscribe_log();
}else{
ns_rpc_subscription_close(s,NULL,SERVER_ERROR_ACCESS_DENIED,NULL);
}
}
void api_cb_log_unsubscribed(NS_RPC_SUBSCRIPTION *s){
if(ns_rpc_subscription_count("log")==1) api_unsubscribe_log();
}
void api_cb_gateway_log_subscribed(NS_RPC_SUBSCRIPTION *s){
int err=0;
USER *u=api_user_con(s->c);
char *path=json_str(s->options,"path");
GW *gw=gw_get_gw_by_path(path);
if(!acs(u,path,ACS_TYPE_VIEW,1)){
err=SERVER_ERROR_ACCESS_DENIED;
goto exit;
}
if(!gw){
err=SERVER_ERROR_OBJECT_NOT_FOUND;
goto exit;
}
JSTR *t=&temp_str;
jstr_reset(t);
jstr_opn_obj(t);
jstr_akey_astr(t,"mac",0,gw->mac,0);
jstr_cls_obj(t);
ns_rpc_subscribe_proxy(srv_drv_gateway->c,"gateway_log",t->text,t->len,s);
exit:
if(err) ns_rpc_subscription_close(s,NULL,err,NULL);
}
void api_cb_gateway_log_unsubscribed(NS_RPC_SUBSCRIPTION *s){
ns_rpc_unsubscribe_proxy(srv_drv_gateway->c,"gateway_log",NULL,0,s);
}
void api_cb_scheduler_setvar_event(NS_RPC_SUBSCRIPTION *rs, void *cb_data){
register_schedule(rs->data);
}
void api_cb_exec_event(NS_RPC_SUBSCRIPTION *rs, void *cb_data){
if(rs->data){
int code=json_int(rs->data,"code");
char *output=json_str(rs->data,"output");
uint32_t cid=json_int(rs->data,"payload/cid");
char *rid=json_str(rs->data,"payload/rid");
char *method=json_str(rs->data,"payload/method");
char *result=json_str(rs->data,"payload/result");
int count;
NS_RPC_SUBSCRIPTION **ss=ns_rpc_get_subscriptions(cid,"async",0,&count);
if(count){
JSTR *s=&temp_str;
jstr_reset(s);
jstr_opn_obj(s);
jstr_akey_raw(s,"id",0,rid,0);
if(code==0){
if(str_cmp(method,"fdb_import")==0){
char *src=json_str(rs->data,"payload/src");
char *dst=json_str(rs->data,"payload/dst");
char *path=json_str(rs->data,"payload/path");
jstr_akey(s,"result",0);
jstr_opn_arr(s);
char *n;
char *p;
int e;
file_iter_bgn(dst,FILE_TYPE_ANY,n,p)
char *fp=obj_import(p,path,NULL,0,&e);
jstr_opn_obj(s);
jstr_akey_ustr(s,"import",0,n,0);
jstr_akey_ustr(s,"path",0,fp,0);
if(e) jstr_akey_int(s,"error",0,e);
jstr_cls_obj(s);
free(fp);
file_iter_end
jstr_cls_arr(s);
file_remove(dst);
file_remove(src);
//printf("\n\n%s\n\n",s->text);
}else if(str_cmp(method,"backup_restore")==0){
char *dst=json_str(rs->data,"payload/dst");
char *path="/projects";
jstr_akey(s,"result",0);
jstr_opn_arr(s);
char *n;
char *p;
int e;
file_iter_bgn(dst,FILE_TYPE_ANY,n,p)
char pp[PATH_MAX];
snprintf(pp,PATH_MAX,"%s/%s",path,n);
if(obj_exists(pp)){
obj_delete(pp);
}
char *fp=obj_import(p,path,NULL,0,&e);
jstr_opn_obj(s);
jstr_akey_ustr(s,"import",0,n,0);
jstr_akey_ustr(s,"path",0,fp,0);
if(e) jstr_akey_int(s,"error",0,e);
jstr_cls_obj(s);
free(fp);
file_iter_end
jstr_cls_arr(s);
file_remove(dst);
//printf("\n\n%s\n\n",s->text);
}else{
jstr_akey_raw(s,"result",0,result,0);
}
}else{
jstr_akey(s,"error",0);
jstr_opn_obj(s);
jstr_akey_int(s,"code",0,SERVER_ERROR_OPERATION_FAILED);
jstr_akey_astr(s,"message",0,"SERVER_ERROR_OPERATION_FAILED",0);
jstr_akey_ustr(s,"data",0,output,0);
jstr_cls_obj(s);
if(str_cmp(method,"fdb_import")==0){
char *src=json_str(rs->data,"payload/src");
char *dst=json_str(rs->data,"payload/dst");
file_remove(dst);
file_remove(src);
}
}
jstr_cls_obj(s);
for(int i=0; itext,s->len);
}
}
free(ss);
// if(str_cmp(method,"restore_backup")==0){
// acs_clear_cache();
// gw_reload_list();
// prj_reload_vars();
// }
}
}
void api_cb_gateway_info_subscribed(NS_RPC_SUBSCRIPTION *s){
if(!api_is_admin_con(s->c)) ns_rpc_subscription_close(s,NULL,SERVER_ERROR_ACCESS_DENIED,NULL);
//if(!srv_core->connected) ns_rpc_subscription_close(s,NULL,SERVER_ERROR_CORE_OFFLINE,NULL);
if(srv_drv_gateway->connected){
gw_fire_info(s);
}else{
ns_rpc_subscription_close(s,NULL,SERVER_ERROR_DRV_GATEWAY_OFFLINE,NULL);
}
}
void api_cb_ddos_subscribed(NS_RPC_SUBSCRIPTION *s){
if(api_is_admin_con(s->c)){
update_ddos_subs(s,NULL,0);
}else{
ns_rpc_subscription_close(s,NULL,SERVER_ERROR_ACCESS_DENIED,NULL);
}
}
void api_cb_var_update_subscribed(NS_RPC_SUBSCRIPTION *s){
USER *u=api_user_con(s->c);
if(u){
drv_ex_api_subscribe_update(s);
}else{
ns_rpc_subscription_close(s,NULL,SERVER_ERROR_ACCESS_DENIED,NULL);
}
}
void api_cb_var_update_unsubscribed(NS_RPC_SUBSCRIPTION *s){
drv_ex_api_unsubscribe_update(s);
}
void api_cb_aggregate_subscribed(NS_RPC_SUBSCRIPTION *s){
//s->options
int err=0;
USER *u=api_user_con(s->c);
if(!(u && u->admin) && !s->c->is_unix){
err=SERVER_ERROR_ADMIN_ACCESS_REQUIRED;
goto exit;
}
// char *tag_filter=json_str(s->options,"tag_filter");
// if(!tag_filter){
// err=NS_RPC_ERROR_PARAMS;
// goto exit;
// }
var_free_aggr(s->cb_data);
VAR_AGGR *a=calloc(1,sizeof(VAR_AGGR));
char *function=json_str(s->options,"function");
char *cron=str_dup(json_str(s->options,"cron"));
a->change_id=-1;
a->tag_filter=str_dup(json_str(s->options,"tag_filter"));
a->val_filter=str_dup(json_str(s->options,"val_filter"));
a->val_expr=str_dup(json_str(s->options,"val_expr"));
a->prefix=str_dup(json_str(s->options,"prefix"));
a->unrel=json_int_def(s->options,"unrel",0);
a->period=json_int_def(s->options,"period",1000);
a->var=str_dup(json_str(s->options,"var"));
a->varindex=drv_index_by_name(a->var);
if(!function) function="summ";
a->function=str_dup(function);
if(cron){
a->cron=malloc(sizeof(cron_expr));
cron_parse_cron(cron,a->cron);
}
s->cb_data=a;
if(!a->cron && !a->period) a->period=1000;
var_aggregate_update(s);
exit:
if(err) ns_rpc_subscription_close(s,NULL,err,NULL);
}
void api_cb_aggregate_unsubscribed(NS_RPC_SUBSCRIPTION *s){
var_free_aggr(s->cb_data);
}
void api_free(){
}
void api_init(){
ns_rpc_on_api_request = api_cb_ns_rpc_api_request;
ns_rpc_on_api_response = api_cb_ns_rpc_api_response;
service_api("system_ping",api_system_ping,NULL,NULL,"result");
service_api("system_ready",api_system_ready,NULL,NULL,"result");
service_api("system_get_calendar",api_system_get_calendar,NULL,NULL,"result");
service_api("system_set_calendar",api_system_set_calendar,NULL,NULL,"result");
service_api("system_time",api_system_time,NULL,NULL,"result");
service_api("system_reset_time",api_system_reset_time,NULL,"params","result");
service_api("system_set_time",api_system_set_time,NULL,"params","result");
service_api("system_html_files",api_system_html_files,NULL,"folder","result");
service_api("system_info",api_system_info,NULL,NULL,"result");
service_api("system_access",api_system_access,NULL,"params","result");
service_api("system_groups",api_system_groups,NULL,"params","result");
service_api("system_set_config",api_system_set_config,NULL,"params","result");
service_api("system_reset_config",api_system_reset_config,NULL,"params","result");
service_api("system_check_config",api_system_check_config,NULL,"params","result");
service_api("system_info",api_system_info,NULL,NULL,"result");
service_api("system_services",api_system_services,NULL,NULL,"result");
service_api("system_config_data",api_system_config_data,NULL,"service","result");
service_api("system_config_schema",api_system_config_schema,NULL,"service","result");
service_api("system_log_files",api_system_log_files,NULL,"service","result");
service_api("system_delete_logs",api_system_delete_logs,NULL,"service","result");
service_api("system_start_service",api_system_start_service,NULL,NULL,"result");
service_api("system_stop_service",api_system_stop_service,NULL,NULL,"result");
service_api("system_restart_service",api_system_restart_service,NULL,NULL,"result");
service_api("system_reboot",api_system_reboot,NULL,NULL,"result");
service_api("system_check_cron",api_system_check_cron,NULL,NULL,"result");
service_api("editor_hold_object",api_editor_hold_object,NULL,"params","result");
service_api("editor_group_users",api_editor_group_users,NULL,"params","result");
service_api("editor_start_build",api_editor_start_build,NULL,NULL,"result");
service_api("editor_cancel_build",api_editor_cancel_build,NULL,NULL,"result");
service_api("fdb_create",api_fdb_create,NULL,"params","result");
service_api("fdb_create_next",api_fdb_create_next,NULL,"params","result");
service_api("fdb_move",api_fdb_move,NULL,"params","result");
service_api("fdb_clone",api_fdb_clone,NULL,"params","result");
service_api("fdb_copy",api_fdb_copy,NULL,"params","result");
service_api("fdb_delete",api_fdb_delete,NULL,"params","result");
service_api("fdb_save",api_fdb_save,NULL,"params","result");
service_api("fdb_list",api_fdb_list,NULL,"params","result");
service_api("fdb_load",api_fdb_load,NULL,"params","result");
service_api("fdb_access",api_fdb_access,NULL,"params","result");
service_api("fdb_list_doc",api_fdb_list_doc,NULL,"params","result");
service_api("fdb_load_doc",api_fdb_load_doc,NULL,"params","result");
service_api("fdb_save_doc",api_fdb_save_doc,NULL,"params","result");
service_api("fdb_upload",api_fdb_upload,NULL,"params","result");
service_api("fdb_paths",api_fdb_paths,NULL,"params","result");
service_api("fdb_bundle",api_fdb_bundle,NULL,"params","result");
service_api("fdb_prototype_nodes",api_fdb_prototype_nodes,NULL,"params","result");
service_api("fdb_mimic_objects",api_fdb_mimic_objects,NULL,"params","result");
service_api("fdb_export",api_fdb_export,NULL,"params","result");
service_api("fdb_import",api_fdb_import,NULL,"params","result");
service_api("fdb_import_template",api_fdb_import_template,NULL,"params","result");
service_api("fdb_templates",api_fdb_templates,NULL,"params","result");
service_api("fdb_nextname",api_fdb_nextname,NULL,"params","result");
service_api("fdb_search",api_fdb_search,NULL,"params","result");
service_api("user_login",api_user_login,NULL,"params","result");
service_api("user_tokin",api_user_tokin,NULL,"login,browser","result");
service_api("user_get",api_user_get,NULL,"login","result");
service_api("user_changepass",api_user_changepass,NULL,"login","result");
service_api("user_logout",api_user_logout,NULL,NULL,"result");
service_api("user_sessions",api_user_sessions,NULL,"login","result");
service_api("user_active",api_user_active,NULL,NULL,"result");
service_api("user_close_session",api_user_close_session,NULL,"login,tok","result");
service_api("user_save_profile",api_user_save_profile,NULL,"login","result");
service_api("user_list",api_user_list,NULL,"","result");
service_api("user_save",api_user_save,NULL,"new_login,admin","result");
service_api("user_create",api_user_create,NULL,"login,admin","result");
service_api("user_block",api_user_block,NULL,"login","result");
service_api("user_unblock",api_user_unblock,NULL,"login","result");
service_api("user_resetpass",api_user_resetpass,NULL,"login","result");
service_api("user_delete",api_user_delete,NULL,"login","result");
service_api("user_notifications",api_user_notifications,NULL,"params","result");
service_api("user_notifications_watched",api_user_notifications_watched,NULL,NULL,"result");
service_api("backup_create",api_backup_create,NULL,"params","result");
service_api("backup_list",api_backup_list,NULL,"params","result");
service_api("backup_delete",api_backup_delete,NULL,"params","result");
service_api("backup_restore",api_backup_restore,NULL,"params","result");
service_api("gateway_reset_secret",api_gateway_reset_secret,NULL,"mac","result");
service_api("gateway_exec",api_gateway_exec,NULL,"mac,command","result");
service_api("gateway_reboot",api_gateway_reboot,NULL,"mac,command","result");
service_api("gateway_info",api_gateway_info,NULL,"params","result");
service_api("gateway_macs",api_gateway_macs,NULL,"params","result");
service_api("gateway_restart_service",api_gateway_restart_service,NULL,"params","result");
service_api("log_get_server_config",api_log_get_server_config,NULL,"params","result");
service_api("log_get_server_schema",api_log_get_server_schema,NULL,"params","result");
service_api("log_set_server_config",api_system_set_config,NULL,"params","result");
service_api("log_get_gateway_config",api_log_get_gateway_config,NULL,"params","result");
service_api("log_get_gateway_schema",api_log_get_gateway_schema,NULL,"params","result");
service_api("log_set_gateway_config",api_log_set_gateway_config,NULL,"params","result");
service_api("node_list",api_node_list,NULL,"params","result");
service_api("node_prefixes",api_node_prefixes,NULL,"params","result");
service_api("var_list",api_var_list,NULL,"path,list,alarms","result");
service_api("var_set",api_var_set,NULL,"params","result");
service_api("var_get",api_var_get,NULL,"params","result");
service_api("var_info",api_var_info,NULL,"params","result");
service_api("trends_read",api_trends_read,NULL,"params","result");
service_api("trends_log",api_trends_log,NULL,"params","result");
service_api("trends_slice",api_trends_slice,NULL,"params","result");
service_api("license_keys",api_license_keys,NULL,NULL,"result");
service_api("license_add",api_license_add,NULL,NULL,"result");
service_api("license_delete",api_license_delete,NULL,NULL,"result");
service_api("journal",api_journal,NULL,"project","result");
service_api("alarm_ack",api_alarm_ack,NULL,"var","result");
service_api("alarm_unack",api_alarm_unack,NULL,"var","result");
service_api("alarm_shelve",api_alarm_shelve,NULL,"var","result");
service_api("alarm_unshelve",api_alarm_unshelve,NULL,"var","result");
service_api("script_debug",api_script_debug,NULL,"params","result");
service_api("project_info",api_project_info,NULL,"params","result");
service_api("ddos_forget",api_ddos_forget,NULL,"params","result");
service_api("ddos_block",api_ddos_block,NULL,"params","result");
service_api("ddos_unblock",api_ddos_unblock,NULL,"params","result");
service_api("schedule_list",api_schedule_list,NULL,NULL,"result");
service_api("test",api_test,NULL,"params","result");
service_subscription("license",api_cb_license_subscribed,NULL,NULL);
service_subscription("user_update",api_cb_user_update_subscribed,NULL,NULL);
service_subscription("session_update",api_cb_session_update_subscribed,NULL,NULL);
service_subscription("user_notifications",api_cb_user_notifications_subscribed,NULL,NULL);
service_subscription("async",NULL,NULL,"data");
service_subscription("builder",api_cb_builder_subscribed,NULL,"data");
service_subscription("alarms",api_cb_alarms_subscribed,NULL,"data");
service_subscription("refresh_interface",NULL,NULL,"data");
service_subscription("journal_update",NULL,NULL,"data");
service_subscription("log",api_cb_log_subscribed,api_cb_log_unsubscribed,"data");
service_subscription("gateway_info",api_cb_gateway_info_subscribed,NULL,"data");
service_subscription("gateway_log",api_cb_gateway_log_subscribed,api_cb_gateway_log_unsubscribed,"data");
service_subscription("var_update",api_cb_var_update_subscribed,api_cb_var_update_unsubscribed,"data");
service_subscription("aggregate",api_cb_aggregate_subscribed,api_cb_aggregate_unsubscribed,"data");
service_subscription("ddos",api_cb_ddos_subscribed,NULL,"data");
}